My SonOff sketch below. Solder header to board and flash with Arduion IDE, see instructions here --> http://www.superhouse.tv/17-home-automation-control-with-sonoff-arduino-openhab-and-mqtt/ I used the green on-board LED to blink, showing that the loop is running and GPIO14 (available on the header, with outboard resistor and LED for testing only, then removed for production). I soldered short leads with header plug across the push button for connection to a standard wall light switch for manual operation (change of state triggers, not “on” and “off” as marked on wall switch)… You could attach your wall switch to GPIO14 after the programming cable is removed. Good luck.
/*
SonOff_v5.ino
------------------------
SonOff(TM) ESP8266 WiFi smart power switch "hack",
(v2) Added "at device" over ride, (toggle) BUTTON.
(v3) Fix relay ON after initialization
(v4) Revised to act like a "3 way switch" (external switch soldered to button)
(v5) Adds blinking (loop running) LED and adds GPIO14 (outboard optional) LED to mimic relay for testing
------------------------
Mar 16, 2018 (v5)
Mar 13, 2018 (v4)
Mar 1, 2018 (v3)
Dec 21, 2016 (v2)
By sparkgap
------------------------
This Shetch is based on....
Remote (Ham Radio) Antenna Switch by KE2ZT, Published in QST Sept 2016, pg42
------------------------
Relay and status LED are activated by addresssing URLs w/ browser as follows:
http://192.168.1.151:8881/on //Switch ON
http://192.168.1.151:8881/off //Switch OFF
http://192.168.1.151:8881/poll // To poll switch status
These IPs and ports must match your router configuration.
To activate from the internet side of your router,
replace the above IPs with the IP address of your router.
If you do not have a
dedicated IP address your IP may change after power loss.
------- programming cable ---------
CAUTION - Disconnect A/C mains before attaching Ribbpn Cable
Programming Header Pinout is as follows:
X GPIO14
X GND
X TX (GPIO1)
X RX (GPIO13)
X 3.3V (pin closest to the Reset Button)
------- uploading ------
IDE - Select Generic ESP8266 Module (load board from Git if not already done)
IDE - Flash Mode = DOUT (required for Sonoff v1.1)
IDE - Flash Size = 1M/(64)
Disable McAfee Real time Scan
Hold reset button down, power-up, release reset, then upload.
------- GPIO use ---------
Relay .......... GPIO12
LED ............ GPIO13 (green onboard LED - blinks to show loop is running
LED2............ GPIO14 (optional outboard LED - mimics relay for testing)
Reset Button ... GPIO0
-------------------------
*/
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiClient.h>
const char* ssid = "craftyglass";
const char* password = "hamradio";
// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(8882); // Assign a unique port number in your router <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//
// This is where we define the pins mapped to relay switches
#define LED 13 // GPIO13
#define LED2 14 // GPIO14
#define RELAY 12 // GPIO12
#define BUTTON 0 // GPIO0
//
// This is where relay action may be inverted.
#define LED_ON 0
#define LED_OFF 1
#define RELAY_SELECT 1
#define RELAY_DESELECT 0
//
int pollVar; // Status 1=on 2=off
long snapshot = millis(); // BUTTON setup
long settle_time = 200; // BUTTON setup
int busy = false; // BUTTON setup
int last_was_push = false; // BUTTON setup
int action_counter = 1; // BUTTON setup
int illuminated = false; // LED blink
long timestamp = millis(); // LED blink
void setup() {
Serial.begin(115200);
delay(10);
// prepare GPIOs
pinMode(LED, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(RELAY, OUTPUT);
pinMode(BUTTON, INPUT);
// deselect RELAY upon bootup
digitalWrite(RELAY, RELAY_DESELECT);
digitalWrite(LED2, 0);
delay(100);
pollVar = 2;
//
Serial.println("Relay is deselected");
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
//
IPAddress ip(192, 168, 1, 152); // Assign a unique IP address in your router <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
WiFi.config(ip, gateway, subnet);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
Serial.println("The Receiver is now Connected..");
//
Serial.print("Button quiescent state is ");
Serial.println( digitalRead (BUTTON)); // should be 1
}
void loop() {
//******************************************
// Button Debouncing and Button Action
// Connect wall light Switch across push button
// Acts like what is called a "3 way Switch" (WiFI or Local)
//******************************************
if (digitalRead (BUTTON) == 0 && last_was_push == false && busy == false)
{ last_was_push = true;
busy = true;
Serial.println("Transition to Push");
}
if (digitalRead (BUTTON) == 1 && last_was_push == true && busy == false)
{ last_was_push = false;
busy = true;
Serial.println("Transition to Unpush");
}
if ( millis() - snapshot > settle_time && busy == true ) // Timeout
{ if (pollVar == 2)
{ digitalWrite(RELAY, RELAY_SELECT);
digitalWrite(LED2, 1) ;
pollVar = 1;
}
else
{ if (pollVar == 1)
{ digitalWrite(RELAY, RELAY_DESELECT);
digitalWrite(LED2, 0) ;
pollVar = 2;
}
}
Serial.print("Action Count = ");
Serial.println(action_counter);
Serial.println("");
action_counter = action_counter + 1;
snapshot = millis();
busy = false;
}
// ***************************************************
// Add LED BLINK
// ***************************************************
if ( millis() - timestamp > 500 && illuminated == false )
{ digitalWrite(LED, LED_ON);
illuminated = true;
timestamp = millis();
}
if ( millis() - timestamp > 500 && illuminated == true )
{ digitalWrite(LED, LED_OFF);
illuminated = false;
timestamp = millis();
}
// ****************************************************
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait until the client sends some data
Serial.println("new client");
while (!client.available()) {
delay(1);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
Serial.println(req);
client.flush();
// Match the request
String val;
String backColor = "<body bgcolor=\"#000000\" text=\"#FFFFFF\">\r\n";
//
//
if (req.indexOf("/on ") != -1) //ON test
{
digitalWrite(RELAY, RELAY_SELECT);
digitalWrite(LED2, 1);
val = "<h1 style=\"color:red;\">Switch is ON</h1>";
pollVar = 1;
}
else if (req.indexOf("/off ") != -1) //OFF test
{
digitalWrite(RELAY, RELAY_DESELECT);
digitalWrite(LED2, 0);
val = "<h1 style=\"color:white;\">Switch is OFF</h1>";
pollVar = 2;
}
else if (req.indexOf("/poll ") != -1) //poll test
{
if (pollVar == 1) {
val = "<h1 style=\"color:red;\"> Switch status is ON</h1>";
}
if (pollVar == 2) {
val = "<h1 style=\"color:white;\"> Switch status is OFF</h1>";
}
}
else {
Serial.println("invalid request");
val = "<blink><h1 style=\"color:yellow;\">INVALID REQUEST!!</h1></blink>";
}
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n";
s += backColor;
s += "<h1><center>SOnOff (TM) <br>WiFi actuated Power Switch</h1><center> ";
s += "<center>" + val + "</center>";
s += "</body></html>\n";
// Send the response to the client
client.print(s);
delay(1);
client.stop();
client.flush();
Serial.println("Client disonnected");
// The client will actually be disconnected
// when the function returns and 'client' object is detroyed
}