Items used:
- LOLIN D1 mini V3.1.0 (ESP8266)
- LOLIN Relay Shield V2.0.0
// Load Wi-Fi library
#include <ESP8266WiFi.h>
// Replace with your network credentials
const char* ssid = "mySSID";
const char* password = "VerySecret";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliary variables to store the current output state
String relayState = "OFF";
// we will have the relay on 5
const int relay = 5;
void setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(relay, OUTPUT);
// set the relay off by default
digitalWrite(relay, LOW);
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
// we match the LED state to the relay state
digitalWrite(LED_BUILTIN, HIGH); // High is off, low is on
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/plain");
client.println("Connection: close");
// turns the GPIOs on and off
if (header.indexOf("GET /relay/on") >= 0) {
Serial.println("Relay on");
relayState = "ON";
digitalWrite(LED_BUILTIN, LOW); // High is off, low is on
digitalWrite(relay, HIGH);
} else if (header.indexOf("GET /relay/off") >= 0) {
Serial.println("Relay off");
relayState = "OFF";
digitalWrite(relay, LOW);
digitalWrite(LED_BUILTIN, HIGH); // High is off, low is on
}
else if (header.indexOf("GET /relay/status") >= 0) {
Serial.print("Sending status: ");
Serial.println(relayState);
client.println();
client.print(relayState);
client.println();
}
client.println();
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
delay(1);
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
Now for the OpenHab side
Here, I’m making use of the HTTP binding (and the REGEX mapping), and we basically have 3 calls we need to handle
And so our items definition is simple to handle those 3 cases:
Switch MyRelay "MyRelay" <switch> ( gSwitches, gRelay ) { http=">[ON:GET:http://<IP Address>/relay/on] >[OFF:GET:http://<IP Address>/relay/off] <[http://<IP Address>/relay/status:10000:REGEX((.*))]"}
And that is basically it – I can now control the on/off of my relays, and check on the current status.
Conclusion / Finishing Thoughts
Some obvious points to consider are:
- Lack of security – anything that can reach the IPs of the relays can manipulate their state
- Lack of rate limiting – a follow up from the 1st point is that we don’t do any cooldowns or rate limiting to prevent accident or maliciousness from repeatedly toggling the relays, potentially damaging the relay and worse, the appliance
- Updating the relays – requires them to be disconnected and connected via USB to a PC/programmer