03/2017

A simple Wi-Fi http server for
Sonoff Basic as Arduino access point


Sonoff Basic device Sonoff Basic device
Compiler settings

// ******************** SONOFF BASIC *******************************
// HTTP server - Access point mode V1.6 / 2018-03-18 for SONOFF BASIC
// Copyright 2018 Pavel Janko, www.fancon.cz
// MIT license, http://opensource.org/licenses/MIT
// without any cloud
// POST or GET method selector,
// WiFi channel 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 external 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 from serial, restart the device.
//
// IP address of AP is 192.168.4.1
// Default access point password is "password"
//
// 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://192.168.4.1/firmware and upload your *.bin
// file.
//
//
//   |---------------|-----------|------------------|
//   |  Button       | GREEN LED |      Action      |
//   |---------------|-----------|------------------|
//   |short press    |relay state|change relay state|
//   |long press > 3s|  change   |restart ESP8266   |
//   |      --       |flashing   |after restart     |
//   |      --       |short flash|client got page   |
//   |before power on|    --     |flash mode only   |
//   |---------------|-----------|------------------|

#include <Ticker.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#define APSSID          "SONOFF_AP"// AP SSID 
#define APPASSWORD      "password" // AP password must be longer then 7 characters
#define WIFICHANNEL     1          // Set WiFi Channel 1-13
#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 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       // [s] time between button read
#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;    // Green LED off
bool    RelayState      = false;   // Relay off
bool    ButtonFlag      = false;
char    ButtonCount     = 0;
String  OnButt;
String  OffButt;
String  buff;
ESP8266WebServer HttpServer(SERVERPORT);
ESP8266HTTPUpdateServer httpUpdater;
Ticker ButtonTick;           // Preparing for periodic button reading
//-----------------------------------------------------------------
void setup(void) {
  //Serial.begin(115200);
  WiFi.persistent(false);
  WiFi.softAP(APSSID, APPASSWORD, WIFICHANNEL);
  WiFi.mode(WIFI_AP);
  /* set ports */
  pinMode(BUTTONPIN, INPUT);
  pinMode(LEDPIN, OUTPUT);
  pinMode(RELAYPIN, OUTPUT);
  RelaySet(RelayState);
  httpUpdater.setup(&HttpServer, OTAPATH, OTAUSER, OTAPASSWORD);
  HttpServer.on("/", HTTP_GET, ModifySendPage);
  HttpServer.on("/", HTTP_POST, ModifySendPage);
  HttpServer.onNotFound(handleNotFound);
  HttpServer.begin();
  for (int i = 0; i < 20; i++) {
    GreenLedSet(!LedState);
    delay(100);
  }
  ButtonTick.attach(BUTTONTIME, ButtonFlagSet);
}
//-----------------------------------------------------------------
void loop(void) {
  HttpServer.handleClient();              // Listen for HTTP requests from clients
  if (ButtonFlag) GetButton();            // Periodic serve button
}
//-----------------------------------------------------------------
void SendPage() {
  GreenLedSet(!LedState);
  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);
  delay(20);
  GreenLedSet(!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 relay */
  if (digitalRead(BUTTONPIN) == false ) ++ButtonCount;
  if (digitalRead(BUTTONPIN) == true && ButtonCount > 1 && ButtonCount < 12 ) {
    RelaySet(!RelayState); // change relay
  }
  /* long press button restart */
  if (ButtonCount > 12) {
    GreenLedSet(!LedState);
    ButtonTick.detach();    // Stop Tickers
    /* Wait for release button */
    while (!digitalRead(BUTTONPIN))yield();
    delay(100);
    ESP.restart();
  }
  if (digitalRead(BUTTONPIN) == true ) ButtonCount = 0;
  ButtonFlag = false;
}
/* 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);
  GreenLedSet(!SetRelayState);
}
/* set green LED */
void GreenLedSet(bool SetLedState) {
  LedState = SetLedState;     // set green LED
  digitalWrite(LEDPIN, LedState);
}
void ButtonFlagSet(void)
{
  ButtonFlag = true;
}

Here is Arduino sketch