I'm writing this watering system controller in such a way that it will be programmable by users using nothing more than a wifi-connected web browser and web forms. All the required code and web forms will be contained within the D1 mini and SD shield that I am using.
Part of the initialisation I want to use is to have the D1 wake up for the first time as an unsecured access point and output a web form asking for the required mode (access point or client), SSID and password that the controller will use from then on.
Now, in program development up to the point of adding the code to implement the above, I have had the controller hard-coded as a client connecting to my own secured access point. That works fine. My problem is that when I run setup() with the new code implementing the unsecured access point at the start up the function - that is BEFORE the ESP8266 sees any of the old code setting up the secure client, I see messages output in the diagnostic window saying that WiFi has reconnected to my secure access point - That is, somewhere it has cached the required mode information, SSID and password to my access point when that information no longer exists in the program I have repeatedly downloaded before and after power-down/power-up cycles etc. etc.
Does the ESP8266 need to be told to FORGET this information like one has to do with smartphones and other WiFi clients?
If so, How do I do it?
Included below is the code I am using for this setup. Note that I am declaring separate WiFi and server class objects for the setup which will be destroyed once the setup completes. The WiFi and server class objects which will be used after setup is done have been declared either in the library or globally in my program but the code to initialise them doesn't run until this initial setup is done.
##############################################################################
ESP8266WebServer server(80);
// ################################################################## HANDLE SETUP
// This function processes the 'content' returned from the setup.htm web form.
bool handleFileSetup(String path){
int i, j;
String modeName = "";
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.println("handleFileSetup: " + path);
#endif // _DEBUG_
if((j=server.args()) < 3) {
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.println("ERROR: Too few arguments returned");
DBG_OUTPUT_PORT.flush();
#endif // _DEBUG_
return FALSE;
}
#if defined(_DEBUG_)
for(i=0; i < j; i++) {
DBG_OUTPUT_PORT.printf("argName(%d) = \"%s\", arg(%d) = \"%s\"\r\n", i, server.argName(i).c_str(), i, server.arg(i).c_str());
}
DBG_OUTPUT_PORT.flush();
#endif // _DEBUG_
if(server.argName(0) == "access" || server.argName(0) == "client") {
modeName = server.arg(0);
} else {
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.println("ERROR: Arg[0] should be \"access\" or \"client\"");
DBG_OUTPUT_PORT.flush();
#endif // _DEBUG_
return FALSE;
}
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.println("Operation File is: " + modeName);
DBG_OUTPUT_PORT.flush();
#endif // _DEBUG_
if(modeName == "") return FALSE;
gotUpdatedTimeFlag = TRUE; // Not a time flag here, just flagging that handleFileSetup() has run.
// This function is not yet completely written
return handleFileGET(modeName);
return TRUE;
}
// ##################################################################
// Re-entrant function to print the directory of the SD card.
// lifted from one of the library examples
#ifdef _DEBUG_
void printDirectory(File dir, int numTabs)
{
while(TRUE) {
File entry = dir.openNextFile();
if (! entry) {
break; // no more files
}
for (uint8_t i=0; i<numTabs; i++) {
DBG_OUTPUT_PORT.print('\t');
}
DBG_OUTPUT_PORT.print(entry.name());
if (entry.isDirectory()) {
DBG_OUTPUT_PORT.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
DBG_OUTPUT_PORT.print("\t\t");
DBG_OUTPUT_PORT.println(entry.size(), DEC);
}
entry.close();
}
}
#endif // _DEBUG_
// ################################################################## SETUP
void setup(void) {
uint16_t i;
#if defined(_DEBUG_)
uint8_t v;
DBG_OUTPUT_PORT.begin(115200);
while( ! DBG_OUTPUT_PORT);
DBG_OUTPUT_PORT.print("\n");
DBG_OUTPUT_PORT.setDebugOutput(true);
DBG_OUTPUT_PORT.printf("Stack now at %09X\r\n", &v);
#endif // _DEBUG_
SD.begin();
#if defined(_DEBUG_)
{
File root = SD.open("/");
printDirectory(root, 0);
}
#endif // _DEBUG_
pinMode(INITIALISE_TEST_PIN, INPUT);
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.printf("SSID = \"%s\"\r\n", ssid.c_str());
#endif // _DEBUG_
if(digitalRead(INITIALISE_TEST_PIN) || ssid == "") {
uint32_t j;
ssid = "";
// Wifi mode and credentials unknown, so use an unsecured access
// point and web server to get the values for those
#if defined(_DEBUG_)
i = 1; DBG_OUTPUT_PORT.println("Configuring setupWiFi mode and credentials");
#endif // _DEBUG_
ESP8266WiFiClass setupWiFi;
setupWiFi.softAP("WaterAP"); // Unsecured connection - no password.
while(setupWiFi.status() != WL_CONNECTED) {
delay(500);
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.print(".");
#endif // _DEBUG_
}
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.println("Setup WiFi connected");
#endif // _DEBUG_
ESP8266WebServer setupServer(80);
setupServer.on("/", HTTP_GET, [](){ if(!handleFileGET("setup.htm")) server.send(404, "text/plain", "FileNotFound"); });
setupServer.on("/setup.htm", HTTP_POST, [](){ if(!handleFileSetup("setup.htm")) server.send(404, "text/plain", "FileNotFound"); });
setupServer.begin();
#if defined(_DEBUG_)
DBG_OUTPUT_PORT.println("HTTPD Setup Server started");
#endif // _DEBUG_
while( ! gotUpdatedTimeFlag) {
setupServer.handleClient(); // NB: This is not a blocking function
}
}
gotUpdatedTimeFlag = FALSE; // Repeat initialisation of this flag.
while(1);