03/2017
A simple Wi-Fi http server for
Sonoff Basic as Arduino access point
- POST or GET method selector
- HTTP BASIC authentication
- simply OTA from browser
- for any classic esp8266 too (with at least 1MB of memory for OTA)
// ******************** 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;
}