//********************** Sonoff Basic **************************** // HTTP server - controller V1.6 / 2018-03-18 for SONOFF Basic as server // Copyright 2018 Pavel Janko, www.fancon.cz // MIT license, http://opensource.org/licenses/MIT // Wi-Fi Protected Setup with PBC ready, // mDNS responder for connect by name, // POST or GET method selector, // HTTP BASIC authentication, // supports simply OTA from browser. // // Tested with ARDUINO ESP8266 2.4.1, IDE 1.8.5 // Sonoff Basic has 1MB flash memory only ! // For flashing disconnect the AC power! Power Sonoff only from // the USB to Serial converter for your safety ! // Uploading a new application to the Sonoff cancel original firmware ! // Set Generic ESP8266 or ESP8285 by chip types and 1MB flash memory. // It can also be a classic esp8266 (with at least 1MB of memory for OTA). // After flash restart the device. // // To connect to an access point, hold down the Sonoff button for about // three seconds (green LED is lit permanently) and activate WPS // (Wi-Fi Protected Setup) with PBC (Push Button Configuration) on your // Access point. // // For mDNS install Bonjour to your Windows - https://support.apple.com/bonjour // or Avahi for your Linux - https://www.avahi.org/ // mDNS name is defined as "sonoff" below here. Just enter http://sonoff.local // into the browser. But in my case, mDNS is sometimes // slower than a direct IP address. // // For web authentication set #define WWWAUTHENTI true and // your WWWUSERNAME and WWWPASSWORD below only. // // For OTA activation set OTAUSER, OTAPASSWORD and then in operation // write to browser address row http://sonoff.local/firmware or direct IP address // and upload your *.bin // file. // // |---------------|-----------|--------------------| // | Button | GREEN LED | Action | // |---------------|-----------|--------------------| // |short press |relay state|change relay state | // |long press > 3s| change |wait for WPS from AP| // | -- | flashing |after restart | // | -- |short flash|client got page | // |before power on| -- |flash mode only | // |---------------|-----------|--------------------| // #include #include #include #include #include #define WWWAUTHENTI false // Set true for web authentication #define WWWUSERNAME "admin" // Set www user name #define WWWPASSWORD "admin" // Set www user password #define OTAUSER "admin" // Set OTA user #define OTAPASSWORD "admin" // Set OTA password #define OTAPATH "/firmware"// Set path for update #define MDNSNAME "sonoff" // Set local mDNS name #define HTTPMETHOD "POST" // Set "GET" or "POST" method #define BUTTONPIN 0 // GPIO0 button pin #define RELAYPIN 12 // GPIO12 relay pin #define LEDPIN 13 // GPIO13 GREEN LED (active low) #define BUTTONTIME 0.25 #define WIFIDOGTIME 5 #define SERVERPORT 80 #define BUTTONON "color: green; border: 3px #fff outset;" #define BUTTONOFF "color: red; border: 3px #fff outset;" #define BUTTONNOACT "color: black; border: 7px #fff outset;" bool LedState = true; // LED off bool RelayState = false; // Relay off bool ButtonFlag = false; bool WifiDogFlag = false; bool RafHo = false; char ButtonCount = 0; String OnButt = BUTTONNOACT; String OffButt = BUTTONOFF; String HowDelka; String buff; ESP8266WebServer HttpServer(SERVERPORT); ESP8266HTTPUpdateServer httpUpdater; Ticker ButtonTick; // Preparing for periodic button reading Ticker WifiDogTick; // preparing for test WiFi connection //----------------------------------------------------------------- void setup(void) { Serial.begin(115200); WiFi.begin(); /* set ports */ pinMode(RELAYPIN, OUTPUT); pinMode(LEDPIN, OUTPUT); pinMode(BUTTONPIN, INPUT); RelaySet(RelayState); Serial.println('\n'); Serial.println("Connecting "); /* wait for WiFi connect */ while (WiFi.status() != WL_CONNECTED) { GetButton(); delay(250); LedSet(!LedState); Serial.print("."); } LedSet(true); Serial.println('\n'); Serial.print("Connected to "); Serial.println(WiFi.SSID()); Serial.print("IP address:\t"); Serial.println(WiFi.localIP()); ButtonTick.attach(BUTTONTIME, ButtonFlagSet); WifiDogTick.attach(WIFIDOGTIME, WifiDogFlagSet); httpUpdater.setup(&HttpServer, OTAPATH, OTAUSER, OTAPASSWORD); MDNS.begin(MDNSNAME); HttpServer.on("/", HTTP_GET, ModifySendPage); HttpServer.on("/", HTTP_POST, ModifySendPage); HttpServer.onNotFound(handleNotFound); HttpServer.begin(); Serial.println("HTTP server started"); } //----------------------------------------------------------------- void loop(void) { HttpServer.handleClient(); // Listen for HTTP requests from clients if (ButtonFlag) GetButton(); // Periodic serve button if (WifiDogFlag) WifiTest(); // Periodic test WiFi connection }//----------------------------------------------------------------- void SendPage() { LedSet(!LedState); buff = "\n"; buff += "\n"; buff += "\n"; buff += "\n"; buff += "SONOFF - Basic\n"; buff += "
\n"; buff += "
\n"; buff += "

Sonoff ID : " + String(ESP.getChipId()) + "
\n"; buff += "\n"; buff += "\n"; buff += "

\n"; HttpServer.send(200, "text/html", buff); delay(20); LedSet(!LedState); } /* Send HTTP status 404 Not Found */ void handleNotFound() { HttpServer.send(404, "text/plain", "404: Not found"); } /* Read button on GPIO0*/ void GetButton(void) { /* short press butoon to change state of LED */ if (digitalRead(BUTTONPIN) == false ) ++ButtonCount; if (digitalRead(BUTTONPIN) == true && ButtonCount > 1 && ButtonCount < 12 )RelaySet(!RelayState); /* long press button - WPS mode */ if (ButtonCount > 12) { bool Before=LedState; RelaySet(false); // Relay OFF LedSet(!Before); // LED change ButtonTick.detach(); // Stop Tickers WifiDogTick.detach(); while (!digitalRead(BUTTONPIN))yield(); delay(100); StartWpsWaiting(); } if (digitalRead(BUTTONPIN) == true ) ButtonCount = 0; ButtonFlag = false; } /* Service Wi-Fi Protected Setup with Push Button Configuration */ void StartWpsWaiting(void) { WiFi.persistent(false); WiFi.mode(WIFI_STA); bool RafHo = false; String HowDelka = ""; /* Wait for access point WPS */ Serial.println(""); Serial.println("Wait for WPS"); do { RafHo = WiFi.beginWPSConfig(); Serial.print("*"); HowDelka = WiFi.SSID(); } while (RafHo == false || HowDelka.length() == 0); Serial.println(""); Serial.println(WiFi.SSID()); Serial.println(WiFi.psk()); delay(500); ESP.restart(); } /* change state of relay */ void ModifySendPage(void) { if (WWWAUTHENTI == true) { /* request for www user/password from client */ if (!HttpServer.authenticate(WWWUSERNAME, WWWPASSWORD)) return HttpServer.requestAuthentication(); } if (HttpServer.arg("R1ON") == "ON")RelaySet(true); if (HttpServer.arg("R1OFF") == "OFF")RelaySet(false); SendPage(); } /* set relay */ void RelaySet(bool SetRelayState) { if (SetRelayState == true) { OnButt = BUTTONON; OffButt = BUTTONNOACT; } if (SetRelayState == false) { OnButt = BUTTONNOACT; OffButt = BUTTONOFF; } RelayState = SetRelayState; digitalWrite(RELAYPIN, RelayState); LedSet(!SetRelayState); } /* set green LED */ void LedSet(bool SetLedState) { LedState = SetLedState; // set green LED digitalWrite(LEDPIN, LedState); } /* If disconnected WiFi then restart */ void WifiTest(void) { if (WiFi.status() != WL_CONNECTED) { ESP.restart(); } WifiDogFlag = false; } void ButtonFlagSet(void) { ButtonFlag = true; } void WifiDogFlagSet(void) { WifiDogFlag = true; }