/* Generic GPIO Control by HTTP REST interface */ /* Modify GPIO by accessing DEVICE_IP/gpio?gpio=[GPIO]&value=[0|1] */ /* At first boot it creates a WiFi access point */ /* and provide a web server on it, so you can configure Wifi ssid */ /* Wifi passwd, and a mDNS hostname */ /* In this mode, device will be available at 192.168.4.1 */ /* Device can also be put in OTA Mode: In this case, if you have */ /* a little flash (512K), it better to disable SPIFFS in */ /* "Flash Size" Menu. Use espota.py to upload OTA */ /* After passing in OTA mode, next boot will be in setup mode */ #include #include #include #include #include #include #include #define EEPROM_SIZE 512 char eeprom[EEPROM_SIZE]; #define BOOTMODE_SETUP 0 #define BOOTMODE_NORMAL 1 #define BOOTMODE_OTA 2 /* EEPROM LAYOUT "BOOTMODE;SSID;PASSWORD;HOSTNAME;" BOOTMODE could be 0 for Setup, 1 for normal use, 2 for OTA Setup mode is trigger by setting GPIO3 to ground or at first boot */ /* Set these to your desired credentials. */ const char *ssid = "ESPConfigurator"; ESP8266WebServer server(80); /* Just a little test message. Go to http://192.168.4.1 in a web browser connected to this access point to see it. */ void handleRoot() { server.send(200, "text/html", "

You are connected


" "Setup
" "ON
" "OFF
" ); } void handleSetup() { server.send(200, "text/html", "
" "
" "
" "
" "
" "
"); } void handleGpio() { if (!server.hasArg("gpio") || !server.hasArg("value")) { server.send(500, "text/plain", "Bad arguments\r\n"); return; } digitalWrite(server.arg("gpio").toInt(), server.arg("value").toInt()); pinMode(server.arg("gpio").toInt(), OUTPUT); server.send(200, "text/html", "

GPIO" + server.arg("gpio") + " changed to " + server.arg("value") + "

"); } int saveConfig(int bootMode, String ssid, String password, String host ) { String eeprom; eeprom = String(bootMode) + ";" + ssid + ";" + password + ";" + host + ";"; if (eeprom.length() > EEPROM_SIZE ) return -EMSGSIZE; Serial.println("Saving " + eeprom); for (int i = 0; i < eeprom.length() && i < EEPROM_SIZE; i++) { EEPROM.write(i, eeprom.charAt(i)); } EEPROM.commit(); delay(100); return 0; } void handleSave() { String password; String ssid; String hostName; if (!server.hasArg("ssid") || !server.hasArg("password") || !server.hasArg("host")) { server.send(500, "text/plain", "Bad arguments\r\n"); return; } if (saveConfig(BOOTMODE_NORMAL, server.arg("ssid"), server.arg("password"), server.arg("host")) < 0) { server.send(500, "text/plain", "Cannot Save Credentials (Too long ?Contains \";\"?)\r\n"); return; } server.send(200, "text/html", "

Configuration Saved

"); } void handleNotFound() { String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); } void readEEPROM(int &bootMode, char **ssid, char **password, char **host) { int i = 2; int boot = EEPROM.read(0); if (boot == '1') { bootMode = BOOTMODE_NORMAL; } else if (boot == '2') { bootMode = BOOTMODE_OTA; } else { //Do not need to parse EEPROM when not configured bootMode = BOOTMODE_SETUP; return; } //Read SSID *ssid = &eeprom[2]; do { eeprom[i] = EEPROM.read(i); i++; } while (i < EEPROM_SIZE && eeprom[i - 1] != ';'); eeprom[i - 1] = '\0'; //Read password *password = &eeprom[i]; do { eeprom[i] = EEPROM.read(i); i++; } while (i < EEPROM_SIZE && eeprom[i - 1] != ';'); eeprom[i - 1] = '\0'; //Read HostName *host = &eeprom[i]; do { eeprom[i] = EEPROM.read(i); i++; } while (i < EEPROM_SIZE && eeprom[i - 1] != ';'); eeprom[i - 1] = '\0'; } void setupWifi(int bootmode, int forceSetup, char *confSsid, char *confPassword, char *confHost) { IPAddress myIP; if (bootmode == BOOTMODE_SETUP || forceSetup) { Serial.println("Configuring access point..."); /* You can set a password to the AP here */ WiFi.softAP(ssid); myIP = WiFi.softAPIP(); } else { Serial.println("Connecting to Wifi..."); WiFi.begin(confSsid, confPassword); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); if (!MDNS.begin(confHost)) { Serial.println("Error setting up MDNS responder!"); while (1) { delay(1000); } } Serial.println("mDNS responder started"); myIP = WiFi.localIP(); } Serial.print("My IP address: "); Serial.println(myIP); } void setup() { pinMode(3, OUTPUT); int bootMode; char *confSsid; char *confPassword; char *confHost; delay(1000); Serial.begin(115200); Serial.println(); // Get GPIO 3 Status Serial.swap(); //Switch Serial on GPIO 13 & 15 pinMode(3, INPUT_PULLUP); int txStatus = digitalRead(3); Serial.swap(); // Switch back EEPROM.begin(EEPROM_SIZE); readEEPROM(bootMode, &confSsid, &confPassword, &confHost); if (bootMode == BOOTMODE_NORMAL || bootMode == BOOTMODE_OTA) { Serial.println("Configuration Found !:"); Serial.println(bootMode); Serial.println(confSsid); Serial.println(confPassword); Serial.println(confHost); Serial.println(); } else { Serial.println("No configuration saved"); } Serial.print("GPIO 3 status :"); Serial.print(txStatus); Serial.println(); setupWifi(bootMode, txStatus == 0, confSsid, confPassword, confHost); server.on("/", handleRoot); server.on("/setup", handleSetup); server.on("/save", handleSave); if (bootMode == BOOTMODE_NORMAL) server.on("/gpio", handleGpio); server.onNotFound(handleNotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); }