Home

A simple Wi-Fi http server for
Sonoff Basic and Arduino


Sonoff Basic device Sonoff Basic device


// HTTP server - controller V1.5 / 2018-02-01 for SONOFF BASIC
// Copyright 2017 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.0, 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 1M(64K SPIFFS)
// 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 and upload your *.bin
// file.
//
//   |--------------------------------------------------------------------|
//   |       Button       |     LED     |       Action                    |
//   |--------------------------------------------------------------------|
//   | short press        |  ON or OFF  | change relay state              |
//   | long press > 3sec. |     ON      | wait for WPS from Access point  |
//   |      --            | flashes 2Hz | connection to WiFi              |
//   | before power on    |     --      | flash mode                      |
//   |--------------------------------------------------------------------|
//
#include <Ticker.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#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) {
  WiFi.begin();
  /* set ports */
  pinMode(RELAYPIN, OUTPUT);
  digitalWrite(RELAYPIN, RelayState);
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, LedState);
  pinMode(BUTTONPIN, INPUT);
  /* wait for WiFi connect */
  while (WiFi.status() != WL_CONNECTED) {
    GetButton();
    delay(200);
    digitalWrite(LEDPIN, !LedState);
    delay(50);
    digitalWrite(LEDPIN, LedState);
  }
  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();
}
//-----------------------------------------------------------------
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() {
  buff  = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
  buff += "<html><head>\n";
  buff += "<style type=\"text/css\">\n";
  buff += "html {font-family: sans-serif;color: brown;background:#ffe4c4}\n";
  buff += ".submit {width: 10%; height:5vw; font-size: 100%; font-weight: bold; border-radius: 4vw;}\n";
  buff += "@media (max-width: 1281px) {\n";
  buff += "html {font-size: 3vw; font-family: sans-serif;color: brown;background:#ffe4c4}\n";
  buff += ".submit {width: 40%; height:20vw; font-size: 100%; font-weight: bold; border-radius: 15vw;}}\n";
  buff += "</style>\n";
  buff += "<meta content=\"text/html; charset=utf-8\">\n";
  buff += "<title>SONOFF - Basic</title></head><body>\n";
  buff += "<center>\n";
  buff += "<form action=\"/\" method=\"" + String(HTTPMETHOD) + "\">\n";
  buff += "<h1>Sonoff ID : " + String(ESP.getChipId()) + "<br>\n";
  buff += "<input type=\"submit\" name=\"R1ON\" class=\"submit\" value=\"ON\" style=\"" + OnButt + "\">\n";
  buff += "<input type=\"submit\" name=\"R1OFF\" class=\"submit\" value=\"OFF\" style=\"" + OffButt + "\">\n";
  buff += "</h1></form></center></body></html>\n";
  HttpServer.send(200, "text/html", buff);
}
/* 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 relay */
  if (digitalRead(BUTTONPIN) == false ) {
    ++ButtonCount;
  }
  if (digitalRead(BUTTONPIN) == true && ButtonCount > 1 && ButtonCount < 12 ) {
    RelayState = !RelayState;// change relay state
    digitalWrite(RELAYPIN, RelayState);
    LedState = !RelayState;  //  change LED as relay state
    digitalWrite(LEDPIN, LedState);
    if (RelayState == true) {
      OnButt  = BUTTONON;
      OffButt = BUTTONNOACT;
    }
    else {
      OffButt  = BUTTONOFF;
      OnButt = BUTTONNOACT;
    }
    ButtonCount = 0;
  }
  /* long press button - WPS mode */
  if (ButtonCount > 12) {
    LedState = false;       //  LED ON
    digitalWrite(LEDPIN, LedState);
    RelayState = false;     // Relay OFF
    digitalWrite(RELAYPIN, RelayState);
    ButtonTick.detach();    // Stop Tickers
    WifiDogTick.detach();
    /* Wait for release button */
    while (!digitalRead(BUTTONPIN)) {
      yield();
    }
    delay(100);
    WiFi.persistent(false);
    WiFi.mode(WIFI_STA);
    /* Wait for access point WPS */
    do {
      RafHo = WiFi.beginWPSConfig();
      HowDelka = WiFi.SSID();
    }
    while (RafHo == false || HowDelka.length() == 0);
    delay(500);
    ESP.restart();
  }
  if (digitalRead(BUTTONPIN) == true ) {
    ButtonCount = 0;
  }
  ButtonFlag = false;
}
/* 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;
}
/* 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") {
    OnButt  = BUTTONON;
    OffButt = BUTTONNOACT;
    RelayState = true;  // relay ON
    digitalWrite(RELAYPIN, RelayState);
    LedState = false;   // LED ON
    digitalWrite(LEDPIN, LedState);
  }
  if (HttpServer.arg("R1OFF") == "OFF") {
    OffButt  = BUTTONOFF;
    OnButt = BUTTONNOACT;
    RelayState = false; // relay OFF
    digitalWrite(RELAYPIN, RelayState);
    LedState = true;    // LED OFF
    digitalWrite(LEDPIN, LedState);
  }
  SendPage();
}

Here is Arduino sketch V1.5 with OTA too

Forum

Dec / 2017

UP