ESP8266 DIY Smart Socket – SOFTWARE (3/3)

Good things come to the ones who wait!

It took me longer than I assumed it would, mainly due to software issues, but once I modified the software to my needs, it was much easier to implement new features. ESP8266 DIY Smart Socket gains new options that go beyond the initial tutorial, and this video contains a short presentation as well as the full software guide.

ESP8266 DIY Smart Socket – SOFTWARE

The ESP8266 DIY Smart Socket has the following functionality right now:

  • Tasker (toggle, schedule, notifications)
  • Web UI (toggle, status, schedule)
  • Alexa (toggle)
  • Google Home (toggle)
  • NodeRED – (everything and more)

I mentioned before that ESP8266 DIY Smart Socket can be controlled with virtually anything that can send HTTP POST requests. These requests will control the toggle and the schedule of the smart plug.

Support NotEnoughTech

ESP8266 DIY Smart Socket – ArduinoIDE

To communicate with the socket I’m using an MQTT server running on a Raspberry Pi. The same RPI handless pretty much all the communication between my devices. The protocol is fast, secure (tutorial has no passwords implemented) and it’s supported by ESP8266.

ESP8266 Arduino.ino code
#include 
#include 

// Wifi Connection
const char* ssid = "XXXXX";
const char* password = "XXXXXX";

// MQTT Server address
const char* mqtt_server = "192.168.XXX.XXX";  // ip of your server
const char* topic_internet = "esp/network";   // "online or offline" network status
const char* topic_status = "esp/relay";       // "1 or 0" to toggle socket
const char* topic_c_state = "esp/update";     //"offline"// current state "1 or 0" 
const char* topic_will = "esp/network";       // last will the same as "topic_internet"
const char* ESP_will = "offline";             //last will
const char* ESP_name = "XXXXX";               //Unique MQTT name for your ESP
int pin = 3;                                  //ESP pin RX is the GPIO3 

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup() {
  
  pinMode(3, OUTPUT);
  digitalWrite(3, 0);
//disabled serial after troubleshooting
  Serial.end();
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void setup_wifi() {

  delay(2);
  Serial.println();
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); if ((char)payload[0] == '1') { digitalWrite(pin, 1); client.publish(topic_c_state, "1"); } else { digitalWrite(pin, 0); client.publish(topic_c_state, "0"); } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect(ESP_name, topic_will, 1, false, ESP_will)) { Serial.println("connected"); // Once connected, publish an announcement... client.publish(topic_internet, "online"); // ... and resubscribe client.subscribe(topic_status); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void loop() { if (!client.connected()) { reconnect(); } client.loop(); long now = millis(); if (now - lastMsg > 10000) {
    lastMsg = now;
    ++value;
    snprintf (msg, 75, "online", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish(topic_internet, msg);
  }
}

You can use the code as is, however, bear in mind that you have to modify it to your needs.

// Wifi Connection
const char* ssid = "XXXXX";
const char* password = "XXXXXX";

// MQTT Server address
const char* mqtt_server = "192.168.XXX.XXX";  // ip of your server
const char* topic_internet = "esp/network";   // "online or offline" network status
const char* topic_status = "esp/relay";       // "1 or 0" to toggle socket
const char* topic_c_state = "esp/update";     //"offline"// current state "1 or 0" 
const char* topic_will = "esp/network";       // last will the same as "topic_internet"
const char* ESP_will = "offline";             //last will
const char* ESP_name = "XXXXX";               //Unique MQTT name for your ESP
int pin = 3;                                  //ESP pin RX is the GPIO3 

I kept all the important values together, so you don’t have to jump through the code.

There are few things to note in the code:

void setup() {
 
 pinMode(3, OUTPUT);
 digitalWrite(3, 0);
//disabled serial after troubleshooting
 Serial.end();

I have used the RX pin GPIO03 (as per hardware tutorial) as OUTPUT, therefore disable the serial once you have done troubleshooting your ESP.

The callback function (function executed when MQTT message is received by ESP8266) updates the pin state and also publishes the current state value.

if ((char)payload[0] == '1') { 
 digitalWrite(pin, 1);
 client.publish(topic_c_state, "1"); 
 } 
 else {
 digitalWrite(pin, 0);
 client.publish(topic_c_state, "0");

This feedback is used for the web interface and to update Tasker variable.

The ESP will update the server every 10 sec with ‘online’ message. Additionally, the last will is posted when the ESP8266 DIY Smart Socket goes offline.

 if (client.connect(ESP_name, topic_will, 1, false, ESP_will)) {
 Serial.println("connected");
 // Once connected, publish an announcement...
 client.publish(topic_internet, "online");

The full code can be downloaded at the bottom of this article.

ESP8266 DIY Smart Socket – NodeRED

I know the flow looks scary! Fear not! You only need the whole flow if you are interested in schedules and interface. I will cover everything in this tutorial but you can pick the nodes that you are interested in.

Before we start, open the palette manager and install:

node-red-dashboard
node-red-contrib-bigtimer
node-red-contrib-alexa-home-skill (For Alexa)

These nodes are used in my NodeRED flow.

Online status

When the ESP8266 DIY Smart Socket is connected to the MQTT server it will update its status and update the Web UI. “online” is turned into green and “offline” into a red colour value for the text.

That text is a button node from the dashboard, and colour value is set to {{payload}}.

Current State

When ESP8266 writes a new pin value to control the relay, a new message is published to NodeRED. The message is a binary value (on/off) which is changed into the NO/OFF state and used in the Web UI text node.

Relay control

This is the main flow. The MQTT node will send 1 or 0  to enable and disable the socket. This can be issued with the Web UI node (blue ESP) which sends 1 or 0 based on the switch position. This node also notifies the Android phone via AutoRemote about the update. AR message “esp turnon/turnoff” is sent accordingly.

Support NotEnoughTech
Buy Amazon Echo Dot 

Another way of triggering the ESP8266 DIY Smart Socket is via Alexa. I talked about this node before. As payload (message sent by the node) is a boolean, we have to use a switch again to change it binary. Again, if the state has been changed, the Android phone is notified via AutoRemote.

Lastly, we have an HTTP POST node. We can connect any device (this is the Google Home endpoint) capable of sending POST requests. The request expected has:

{light: "1"} or {light: "0"}

value and it is posted to esp/relay directory. To use HTTP POST with Google Home, use IFTTT and Webhooks. I covered this type of set up here.

Default schedule

Bigtimer nodes are awesome. They come with some many options, that is just mind-blowing. If you are not interested in any schedule overrides, these are the only nodes you need. Select your default timers, and use the 1st output to trigger the MQTT node and Android AutoRemote notifications.

Schedule override

The WebUI and Tasker (or any device capable of HTTP POST) can override the default schedule. There are 2 POST requests – one for the time on and one for the time off.

esp/timeon {timeon: "12:20"}
esp/timeoff {timeoff: "12:20"}

Once again, the value has to be inserted into a payload via  function node:

msg.payload = msg.payload.timeon;
return msg;
AND
msg.payload = msg.payload.timeoff;
return msg;

Then a prefix is applied:

off_override {{payload}}
OR
on_override {{payload}}

as the bigtimer node requires a correct prefix to handle the input. To reset the values to the default, all you need to do is submit payload: “auto” or “default”. Each bigtimer node has to receive the input for time on and off to work properly. If you, like me, use multiple big timer nodes, they can be set to the same values without causing issues.

Web UI

The ESP8266 DIY Smart Socket comes with a Web UI now, where you can perform all the actions or check the status of your socket.

On the left, you see 2 button nodes, 2 text entry nodes, and a Reset button. Writing values into the input fields (delay1000) overwrites a text file. The value is picked up again once the button SET is pressed, and passed over to the template node (needs correct prefix as before). At the same time, the time entered into the web interface is passed over to the text interface on the right.

Reset button writes ‘auto’ to the file and sends the same message directly to the timer nodes and the text node.

Tasker

I set up Tasker to control the ESP8266 DIY Smart Socket and override the default schedule. Please note that I’m using the Near-Perfect Notification to handle my notifications.

Start with Set Server and set the %NodeServer with your IP (or DNS) and the port (default 1880). There are 2 profiles to handle everything.

ESP Smart Notification

TASKER PROFILE: ESP Smart Notification
Profile: ESP Smart Notification 
	Event: AutoRemote [ Configuration:esp ]
Enter: Socket Notifications
	A1: Variable Set [ Name:%ESPsocketValue To:0 Recurse Variables:Off Do Maths:Off Append:Off ] 
	If [ %armessage ~R .*turnon ]
	A2: AutoAppsHub SendCommand [ Configuration:Command: 
	NOTIFICATION=:=ESP Smart Socket=:=The light is ON=:=ESPsocket=:=#5481D4FA=:=2=:=espsocket=:=espsocket=:=Turn OFF=:=ESP TURNOFF 
	Timeout (Seconds):60 ] 
	If [ %armessage ~R .*turnon ]
	
	
	A3: AutoNotification Cancel [ Configuration:Id: ESPsocket Timeout (Seconds):0 ] 
		If [ %anmessage ~R .*turnoff | %armessage ~R .*turnoff ]
	A4: Variable Set [ Name:%ESPsocketValue To:1 Recurse Variables:Off Do Maths:Off Append:Off ] 
		If [ %armessage ~R .*turnoff ]
	A5: Perform Task [ Name:ESP Toggle Priority:%priority Parameter 1 (%par1):end 
		Parameter 2 (%par2): Return Value Variable: Stop:Off ] 
		If [ %anmessage ~R .*turnoff ]

Upon the arrival of an AutoRemote message, e a Notification is created. To do this I simply issue a string of text as an AutoApps command (using Near Perfect Notifications). The notification contains one button – which acts as a shutdown.In addition to that, each time my phone receives an update about the state of the socket %ESPsoketValue is set to the opposite value. I need this to issue a correct POST request later on.

If the ESP8266 DIY Smart Socket is turn on the message received by the POST node is:

on
https://autoremotejoaomgcd.appspot.com/sendmessage?key=YOURKEY&message=esp turnon
off
https://autoremotejoaomgcd.appspot.com/sendmessage?key=YOURKEY&message=esp turnoff

If the received message is ‘off’  the notification gets cancelled, variable %ESPsocketValue is set again.

If this action is triggered by AutoNotification (TURN OFF) button, Notification gets cancelled and the ESP Toggle task is triggered.

ESP Toggle

TASKER TASK: ESP Toggle
ESP Toggle 
	A1: AutoTools Dialog [ Configuration:Dialog Type: List
		Title: ESP Socket Menu
		Title Alignment: Left
		Icon: /storage/emulated/0/DCIM/Join/esp_socket.png
		List Type: Grid
		Text Size: 20
		Images: /ic_lightbulb_outline.png,/ic_alarm_plus-1.png
		Image Width: 100
		Dim Background: true
		Number Of Columns: 2
		Top Margin: 16
		Bottom Margin: 16
		Bottom Buttons Top Margin: 16
		Bottom Buttons Bottom Margin: 16
		Close On Select: true
		Separator: ,
		Command Variable: atcommand
		Cancelable: true
		Turn Screen On: true Timeout (Seconds):60 ] 
		If [ %par1 neq end ]
	A2: HTTP Post [ Server:Port:%NodeServer Path:esp/relay 
		Data / File:light=%ESPsocketValue Cookies: User Agent: 
		Timeout:10 Content Type: Output File: Trust Any Certificate:On ] 
		If [ %atposition eq 1 | %par1 ~ end ]
		
		
	A3: If [ %atposition eq 2 ]	
	

This is a stand alone task that can be triggered via Tasker shortcut from the home screen.

There is an option to toggle the light based on %ESPsocketValue or set an override timer using AutoTools time pickers. The dialog is protected by being triggered from the AutoNotification (TURN OFF button) via %par1 !~ end condition. This variable is issued when Perform Task action happens.

If I click on the bulb – the %atposition = 1 and HTTP POST is sent:

Server:Port:%NodeServer 
Path:esp/relay Data / File:light=%ESPsocketValue

Otherwise, two AutoTools dialogs are displayed. I can set the TIME ON and TIME OFF timers. As the HTTP requests are sent just after the time is picked, I don’t have to override both timers. All I have to check if variable %atdatetime1 has been set.

Conclusion

It’s fair to say, this is an interesting one. I didn’t anticipate the extended features but I’m glad I added it. The ESP8266 DIY Smart Socket has been serving me for over a month now, and I’m very pleased. I hope you picked new skills as well and learned something new!

Keep these Tasker profiles going!
I write about Tasker in my spare time. It takes a lot of time to compress all the research and knowledge into a few minutes long article, a video and ready help files to download. If I saved you some time (time == $$$) consider buying me a beer/coffee/sandwich. Share the article with your friends and hit that like button here and there!
Did you know you can access these tutorials early via my Patreon page? Take look at support me page for more details!
AutoRemote
Price: $3.49
AutoApps
Price: Free+
Support NotEnoughTech
A lot of time and effort goes into keeping NotEnoughTech alive! If my work helped you out, consider buying me a coffee or check out exclusive rewards available to Patreon supporters.
SHARE