Okay this has really been driving me crazy. I'm trying to implement a WiFi manager in my program. (yes I know there's a good library out there for this but that doesn't help me learn anything)
I want to implement my own so I learn how this works. I am using EEPROM to store the wifi ssid and password for my project so I don't have to hard code it and I can switch wifi networks if I have to.
I'm using two functions for this:
The write function:
void eepromWriteString(int startAddress, String stringToWrite) {
char stringChars[stringToWrite.length()];
stringToWrite.toCharArray(stringChars, stringToWrite.length() + 1);
for (int i = 0; i < sizeof(stringChars) + 1; i++) {
Serial.print("Storing ");
Serial.print(stringChars[i]);
Serial.print(" in ");
Serial.println(startAddress);
EEPROM.write(startAddress, stringChars[i]);
startAddress++;
delay(100);
}
EEPROM.commit();
}
The read function:
String eepromGetString(int startAddress) {
char currentChar = EEPROM.read(startAddress);
String gotString;
while (currentChar != '\0' && startAddress < 512) {
currentChar = EEPROM.read(startAddress);
if (currentChar == '\0') {break;}
gotString += currentChar;
startAddress++;
delay(100);
}
return gotString;
}
After writing to EEPROM before resetting I read from it to make sure that it worked and I get back the correct values. So these functions seem to do what I need, however after doing ESP.restart()
I read the EEPROM to connect to wifi and for some reason my SSID gets a '\0' inserted into it at the second character so I only get back the first character and it stops reading at that point. But before the reset calling the same code I get back my data just fine with no random '\0'.
I just don't understand how the code works fine before reset, and after reset the stored data is corrupted with a single null character, I wrote a small test program to see if any other parts of the data are messed up but its not just this single null character. Oh! And by the way the password is just fine it read that no problem its just the SSID.
Please help! This problem has been messing with me for a month. The rest of the code is posted below:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include "vars.h"
// Create WebServer object
ESP8266WebServer server(80);
// Returns true if fan is on
bool getFanState() {
if (digitalRead(TRIGGER_PIN) == HIGH) {
return true;
}
return false;
}
void fanOn() {
bool fanState = getFanState();
if (fanState == false) {
digitalWrite(TRIGGER_PIN, HIGH);
digitalWrite(LED_BUILTIN, HIGH);
}
htmlControls.replace(FAN_OFF_STATUS, FAN_ON_STATUS);
server.send(200, "text/html", htmlControls);
}
void fanOff() {
bool fanState = getFanState();
if (fanState == true) {
digitalWrite(TRIGGER_PIN, LOW);
digitalWrite(LED_BUILTIN, LOW);
}
htmlControls.replace(FAN_ON_STATUS, FAN_OFF_STATUS);
server.send(200, "text/html", htmlControls);
}
void clearEEPROM() {
EEPROM.begin(EEPROM_SIZE);
for (int i = 0; i < EEPROM_SIZE; i++) {
digitalWrite(LED_BUILTIN, HIGH);
EEPROM.write(i, 0);
}
// Set first time setup to true
EEPROM.write(MEM.isFirstTimeSetupAddr, 1);
EEPROM.commit() ? Serial.println("EEPROM Cleared!") : Serial.println("EEPROM Clear Failed");
}
void eepromWriteString(int startAddress, String stringToWrite) {
char stringChars[stringToWrite.length()];
stringToWrite.toCharArray(stringChars, stringToWrite.length() + 1);
for (int i = 0; i < sizeof(stringChars) + 1; i++) {
Serial.print("Storing ");
Serial.print(stringChars[i]);
Serial.print(" in ");
Serial.println(startAddress);
EEPROM.write(startAddress, stringChars[i]);
startAddress++;
delay(100);
}
EEPROM.commit();
}
// Get a string starting from startAddress
String eepromGetString(int startAddress) {
char currentChar = EEPROM.read(startAddress);
String gotString;
while (currentChar != '\0' && startAddress < 512) {
currentChar = EEPROM.read(startAddress);
if (currentChar == '\0') {break;}
gotString += currentChar;
startAddress++;
delay(100);
}
return gotString;
}
/*
* Fall back to AP mode by setting the isFirstTimeSetup variable to true so when it resets it will start in AP mode,
* and the user can go through the setup process again
*/
void fallBackAP() {
EEPROM.begin(EEPROM_SIZE);
// Set to true so when we reset it starts in AP mode
EEPROM.write(MEM.isFirstTimeSetupAddr, 1);
EEPROM.commit() ? Serial.println("Fall back Successful!") : Serial.println("Fall back failed...");
// Initiate a soft reset
ESP.restart();
//Serial.println("Hit Reset button n shit");
}
/**
* This function sets up the wifi for the first time
*
*/
void runFirstTimeSetup(String ssid, String pass)
{
//EEPROM.begin(EEPROM_SIZE);
// Start in SoftAP mode
WiFi.softAP(ssid, pass);
Serial.println("Fan Setup...");
Serial.println(WiFi.softAPIP());
// Scan for network SSIDs to display to the user
int networksFound = WiFi.scanNetworks();
if (networksFound == 0)
{
Serial.println("No Networks Detected...");
server.send(200, "text/html", "No Networks Detected!");
}
// Create an array to store our network credentials
String detectedSSIDs[networksFound];
String ssidHTML[networksFound];
for (int i = 0; i < sizeof(detectedSSIDs) / sizeof(detectedSSIDs[0]); i++) {
detectedSSIDs[i] = WiFi.SSID(i);
for (int o = 0; o < sizeof(detectedSSIDs) / sizeof(detectedSSIDs[0]); o++) {
String element = "<option value=\"" + detectedSSIDs[o] + "\">" + detectedSSIDs[o] + "</option>";
ssidHTML[o] = element;
}
}
// Create a string of the <option> elements
String htmlString;
for(int i = 0; i < sizeof(ssidHTML) / sizeof(ssidHTML[0]); i++) {
htmlString.concat(ssidHTML[i]);
}
// Inject custom HTML into networkSetupPage and serve it
networkSetupPage.replace("<option>", htmlString);
server.on("/", [](){
server.send(200, "text/html", networkSetupPage);
});
server.on("/connect", [](){
NetworkConfig.networkSSID = String(server.arg("ssid"));
NetworkConfig.networkPASS = String(server.arg("password"));
Serial.println("Network SSID: " + NetworkConfig.networkSSID);
Serial.println("Network PASS: " + NetworkConfig.networkPASS);
// Try to connect to WiFi using provided credentials
WiFi.begin(NetworkConfig.networkSSID, NetworkConfig.networkPASS);
while (WiFi.status() == WL_DISCONNECTED) {
Serial.println("Connecting: " + String(WiFi.status()));
if (WiFi.status() == WL_CONNECTED) {
successPage.replace("^networkname^", NetworkConfig.networkSSID);
server.send(200, "text/html", successPage);
// Clear eeprom for new write
clearEEPROM();
// Store SSID
eepromWriteString(MEM.networkSSIDBegin, NetworkConfig.networkSSID);
// Store Password
eepromWriteString(MEM.networkPassBegin, NetworkConfig.networkPASS);
break;
} else if (WiFi.status() == WL_CONNECT_FAILED) {
badPassPage.replace("^networkname^", NetworkConfig.networkSSID);
server.send(200, "text/html", badPassPage);
break;
} else if (WiFi.status() == WL_NO_SSID_AVAIL) {
server.send(200, "text/html", "SSID not found...");
break;
}
}
// Get stored SSID and PASS
NetworkConfig.networkSSID = eepromGetString(MEM.networkSSIDBegin); // These work!
NetworkConfig.networkPASS = eepromGetString(MEM.networkPassBegin); // These work!
Serial.println("SSID: " + NetworkConfig.networkSSID);
Serial.println("Pass: " + NetworkConfig.networkPASS);
// Set first time setup variable to false as we have completed network setup
isFirstTimeSetup = false;
// Write it to EEPROM
EEPROM.begin(EEPROM_SIZE);
EEPROM.put(MEM.isFirstTimeSetupAddr, isFirstTimeSetup);
EEPROM.end() ? Serial.println("Saved First Time Setup") : Serial.println("Failed to save first time setup state...");
// Reset and attempt to connect with saved credentials
Serial.println("Restarting in 5 Seconds");
delay(5000);
ESP.restart();
});
}
void initialize() {
EEPROM.begin(EEPROM_SIZE);
while (!Serial) {
; // Wait for Serial to start
}
server.begin();
EEPROM.begin(EEPROM_SIZE);
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
isFirstTimeSetup = EEPROM.read(MEM.isFirstTimeSetupAddr);
if (isFirstTimeSetup)
{
runFirstTimeSetup(SOFT_AP_SSID, SOFT_AP_PASS);
} else {
// Get the saved data from EEPROM
NetworkConfig.networkSSID = eepromGetString(MEM.networkSSIDBegin); // This fails
NetworkConfig.networkPASS = eepromGetString(MEM.networkPassBegin); // This works
//fallBackAP();
Serial.println("Saved SSID: " + String(NetworkConfig.networkSSID));
Serial.println("Saved Pass: " + String(NetworkConfig.networkPASS));
WiFi.begin(NetworkConfig.networkSSID, NetworkConfig.networkPASS);
while (WiFi.status() == WL_DISCONNECTED) {
Serial.print(".");
delay(500);
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connection Success!");
} else if (WiFi.status() == WL_CONNECT_FAILED) {
Serial.println("Wrong Password...");
fallBackAP();
} else if (WiFi.status() == WL_NO_SSID_AVAIL) {
Serial.println("Wrong SSID...");
fallBackAP();
}
}
EEPROM.end();
server.on("/", []() {
server.send(200, "text/html", htmlControls);
});
server.on("/turnon", fanOn);
server.on("/turnoff", fanOff);
Serial.println(WiFi.localIP());
}
}
void setup() {
Serial.begin(115200);
while (! Serial) {
;
}
delay(200);
initialize();
digitalWrite(TRIGGER_PIN, LOW);
}
void loop() {
// put your main code here, to run repeatedly:
server.handleClient();
}