Skip to content

Instantly share code, notes, and snippets.

@xychix
Created December 24, 2018 07:48
Show Gist options
  • Save xychix/6f982644bb055662485ad645fa23c45a to your computer and use it in GitHub Desktop.
Save xychix/6f982644bb055662485ad645fa23c45a to your computer and use it in GitHub Desktop.
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>
// NOTE: Source code is based on nummerous other projects, it's not my own, neither is it clearly from one other author.
// Considering it GPL would be best I assume.
#define D0 16 //WAKE => 16
#define D1 5 //IOS => 5
#define D2 4 // => 4
#define D3 0 // => 0
#define D4 2 // => 2
#define D5 14 //CLK => 14
#define D6 12 //MISO => 12
#define D7 13 //MOSI => 13
#define D8 15 //CS => 15
#define D9 3 //RX => 3
#define RELAY_PIN D6 //D6 == default on SonOFF
#define TOGGLE_PIN D3 //D3 == default on SonOFF
#define LED_PIN D7 //D7 == default on SonOFF
#define MQTT_VERSION MQTT_VERSION_3_1_1
#define MQTT_SERVER "192.168.XXXX.XXXX" //you MQTT IP Address
const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
const PROGMEM char* MQTT_CLIENT_ID = "sonoff";
const char* MQTT_LIGHT_STATE_TOPIC = "/house/switchConfirm6/";
const char* MQTT_LIGHT_COMMAND_TOPIC = "/house/switch6/";
boolean m_relay_state = false;
boolean fDebug = true;
long lastMsg = 0;
long unsigned int pause = 5000;
int chk;
int TOGGLE_COUNT = 0;
void callback(char* topic, byte* payload, unsigned int length);
void setRelay(char payload);
const char* ssid = "SSID";
const char* password = "XXXXSECRETHEREXXXX";
const char* mqtt_username= "mqtt_username";
const char* mqtt_password = "XXXXSECRETHEREXXXX";
WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);
void setup() {
//initialize the switch as an output and set to HIGH (on) (default)
pinMode(LED_PIN, OUTPUT); // Led 1
digitalWrite(LED_PIN, HIGH); // Led 1
pinMode(RELAY_PIN, OUTPUT); // Relay Switch 1
digitalWrite(RELAY_PIN, LOW); // Relay Switch 1
pinMode(TOGGLE_PIN, INPUT); // Toggle Button
ArduinoOTA.setHostname("My Arduino SONOFF"); // A name given to your ESP8266 module when discovering it as a port in ARDUINO IDE
ArduinoOTA.begin(); // OTA initialization
//start the serial line for debugging
Serial.begin(115200);
delay(100);
//start wifi subsystem
WiFi.begin(ssid, password);
//attempt to connect to the WIFI network and then connect to the MQTT server
reconnect();
//wait a bit before starting the main loop
delay(2000);
}
void loop(){
//reconnect if connection is lost
if (!client.connected() && WiFi.status() == 3) {reconnect();}
// insert button actions here;
//check for button actions
if (digitalRead(TOGGLE_PIN) == LOW) {
m_relay_state = !m_relay_state; // switch state and setRelay accordingly
if(m_relay_state == true){
setRelay('1');
}else{
setRelay('0');
}
delay(1000);
}
//maintain MQTT connection
client.loop();
//MUST delay to allow ESP8266 WIFI functions to run
delay(20);
ArduinoOTA.handle();
}
void setRelay(char payload){
if(payload == '1'){
Serial.print("Set 1");
digitalWrite(RELAY_PIN, HIGH);
digitalWrite(LED_PIN, LOW);
m_relay_state = true;
client.publish(MQTT_LIGHT_STATE_TOPIC, "1");
}
//turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
else if (payload == '0'){
Serial.print("Set 0");
digitalWrite(RELAY_PIN, LOW);
digitalWrite(LED_PIN, HIGH);
m_relay_state = false;
client.publish(MQTT_LIGHT_STATE_TOPIC, "0");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
//convert topic to string to make it easier to work with
String topicStr = topic;
//EJ: Note: the "topic" value gets overwritten everytime it receives confirmation (callback) message from MQTT
//Print out some debugging info
Serial.println("Callback update.");
Serial.print("Topic: ");
Serial.println(topicStr);
Serial.print("Payload: ");
Serial.println(payload[0]);
if (topicStr == MQTT_LIGHT_COMMAND_TOPIC){
Serial.print(MQTT_LIGHT_COMMAND_TOPIC);
//turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
setRelay(payload[0]);
}
}
void reconnect() {
//attempt to connect to the wifi if connection is lost
if(WiFi.status() != WL_CONNECTED){
//debug printing
Serial.print("Connecting to ");
Serial.println(ssid);
//loop while we wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
//print out some more debug once connected
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
//make sure we are connected to WIFI before attemping to reconnect to MQTT
if(WiFi.status() == WL_CONNECTED){
// Loop until we're reconnected to the MQTT server
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Generate client name based on MAC address and last 8 bits of microsecond counter
String clientName;
clientName += "esp8266-";
uint8_t mac[6];
WiFi.macAddress(mac);
clientName += macToStr(mac);
//if connected, subscribe to the topic(s) we want to be notified about
//EJ: Delete "mqtt_username", and "mqtt_password" here if you are not using any
if (client.connect((char*) clientName.c_str(),mqtt_username, mqtt_password)) { //EJ: Update accordingly with your MQTT account
Serial.print("\tMQTT Connected");
client.subscribe(MQTT_LIGHT_COMMAND_TOPIC);
//EJ: Do not forget to replicate the above line if you will have more than the above number of relay switches
}
//otherwise print failed for debugging
else{Serial.println("\tFailed."); abort();}
}
}
}
//generate unique name from MAC addr
String macToStr(const uint8_t* mac){
String result;
for (int i = 0; i < 6; ++i) {
result += String(mac[i], 16);
if (i < 5){
result += ':';
}
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment