Last active
February 2, 2024 20:11
-
-
Save sarasantos/5e60cf40caaf5865cf56f39621501b5c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/********* | |
Rui Santos | |
Complete project details at https://RandomNerdTutorials.com/esp8266-relay-module-ac-web-server/ | |
The above copyright notice and this permission notice shall be included in all | |
copies or substantial portions of the Software. | |
*********/ | |
// Import required libraries | |
#include "ESP8266WiFi.h" | |
#include "ESPAsyncWebServer.h" | |
// Set to true to define Relay as Normally Open (NO) | |
#define RELAY_NO true | |
// Set number of relays | |
#define NUM_RELAYS 5 | |
// Assign each GPIO to a relay | |
int relayGPIOs[NUM_RELAYS] = {2, 4, 14, 12, 13}; | |
// Replace with your network credentials | |
const char* ssid = "REPLACE_WITH_YOUR_SSID"; | |
const char* password = "REPLACE_WITH_YOUR_PASSWORD"; | |
const char* PARAM_INPUT_1 = "relay"; | |
const char* PARAM_INPUT_2 = "state"; | |
// Create AsyncWebServer object on port 80 | |
AsyncWebServer server(80); | |
const char index_html[] PROGMEM = R"rawliteral( | |
<!DOCTYPE HTML><html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<style> | |
html {font-family: Arial; display: inline-block; text-align: center;} | |
h2 {font-size: 3.0rem;} | |
p {font-size: 3.0rem;} | |
body {max-width: 600px; margin:0px auto; padding-bottom: 25px;} | |
.switch {position: relative; display: inline-block; width: 120px; height: 68px} | |
.switch input {display: none} | |
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px} | |
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px} | |
input:checked+.slider {background-color: #2196F3} | |
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)} | |
</style> | |
</head> | |
<body> | |
<h2>ESP Web Server</h2> | |
%BUTTONPLACEHOLDER% | |
<script>function toggleCheckbox(element) { | |
var xhr = new XMLHttpRequest(); | |
if(element.checked){ xhr.open("GET", "/update?relay="+element.id+"&state=1", true); xhr.send(); | |
setTimeout(function(){ xhr.open("GET", "/update?relay="+element.id+"&state=0", true); document.getElementById(element.id).checked = false; xhr.send(); }, 1000);} | |
}</script> | |
</body> | |
</html> | |
)rawliteral"; | |
// Replaces placeholder with button section in your web page | |
String processor(const String& var){ | |
//Serial.println(var); | |
if(var == "BUTTONPLACEHOLDER"){ | |
String buttons =""; | |
for(int i=1; i<=NUM_RELAYS; i++){ | |
String relayStateValue = relayState(i); | |
buttons+= "<h4>Relay #" + String(i) + " - GPIO " + relayGPIOs[i-1] + "</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"" + String(i) + "\" "+ relayStateValue +"><span class=\"slider\"></span></label>"; | |
} | |
return buttons; | |
} | |
return String(); | |
} | |
String relayState(int numRelay){ | |
if(RELAY_NO){ | |
if(digitalRead(relayGPIOs[numRelay-1])){ | |
return ""; | |
} | |
else { | |
return "checked"; | |
} | |
} | |
else { | |
if(digitalRead(relayGPIOs[numRelay-1])){ | |
return "checked"; | |
} | |
else { | |
return ""; | |
} | |
} | |
return ""; | |
} | |
void setup(){ | |
// Serial port for debugging purposes | |
Serial.begin(115200); | |
// Set all relays to off when the program starts - if set to Normally Open (NO), the relay is off when you set the relay to HIGH | |
for(int i=1; i<=NUM_RELAYS; i++){ | |
pinMode(relayGPIOs[i-1], OUTPUT); | |
if(RELAY_NO){ | |
digitalWrite(relayGPIOs[i-1], HIGH); | |
} | |
else{ | |
digitalWrite(relayGPIOs[i-1], LOW); | |
} | |
} | |
// Connect to Wi-Fi | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(1000); | |
Serial.println("Connecting to WiFi.."); | |
} | |
// Print ESP8266 Local IP Address | |
Serial.println(WiFi.localIP()); | |
// Route for root / web page | |
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ | |
request->send_P(200, "text/html", index_html, processor); | |
}); | |
// Send a GET request to <ESP_IP>/update?relay=<inputMessage>&state=<inputMessage2> | |
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) { | |
String inputMessage; | |
String inputParam; | |
String inputMessage2; | |
String inputParam2; | |
// GET input1 value on <ESP_IP>/update?relay=<inputMessage> | |
if (request->hasParam(PARAM_INPUT_1) & request->hasParam(PARAM_INPUT_2)) { | |
inputMessage = request->getParam(PARAM_INPUT_1)->value(); | |
inputParam = PARAM_INPUT_1; | |
inputMessage2 = request->getParam(PARAM_INPUT_2)->value(); | |
inputParam2 = PARAM_INPUT_2; | |
if(RELAY_NO){ | |
Serial.print("NO "); | |
digitalWrite(relayGPIOs[inputMessage.toInt()-1], !inputMessage2.toInt()); | |
} | |
else{ | |
Serial.print("NC "); | |
digitalWrite(relayGPIOs[inputMessage.toInt()-1], inputMessage2.toInt()); | |
} | |
} | |
else { | |
inputMessage = "No message sent"; | |
inputParam = "none"; | |
} | |
Serial.println(inputMessage + inputMessage2); | |
request->send(200, "text/plain", "OK"); | |
}); | |
// Start server | |
server.begin(); | |
} | |
void loop() { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment