diff --git a/Projects/ESP/ESP_Web_Server_Physical_Button_SSE.ino b/Projects/ESP/ESP_Web_Server_Physical_Button_SSE.ino new file mode 100644 index 00000000..6f1609fb --- /dev/null +++ b/Projects/ESP/ESP_Web_Server_Physical_Button_SSE.ino @@ -0,0 +1,239 @@ +/********* + Rui Santos + Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-web-server-physical-button/ + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. +*********/ + +// Import required libraries +#ifdef ESP32 +#include +#include +#else +#include +#include +#endif +#include + +// Replace with your network credentials +const char* ssid = "REPLACE_WITH_YOUR_SSID"; +const char* password = "REPLACE_WITH_YOUR_PASSWORD"; + +const char* PARAM_INPUT_1 = "state"; + +const int output = 2; +const int buttonPin = 4; + +// Variables will change: +int ledState = LOW; // the current state of the output pin +int buttonState; // the current reading from the input pin +int lastButtonState = LOW; // the previous reading from the input pin + +// the following variables are unsigned longs because the time, measured in +// milliseconds, will quickly become a bigger number than can be stored in an int. +unsigned long lastDebounceTime = 0; // the last time the output pin was toggled +unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers + +// Create AsyncWebServer object on port 80 +AsyncWebServer server(80); +AsyncEventSource events("/events"); + +const char index_html[] PROGMEM = R"rawliteral( + + + ESP Web Server + + + + +

ESP Web Server

+ %BUTTONPLACEHOLDER% + + + +)rawliteral"; + +// Replaces placeholder with button section in your web page +String processor(const String& var){ + //Serial.println(var); + if(var == "BUTTONPLACEHOLDER"){ + String buttons =""; + String outputStateValue = outputState(); + buttons+= "

Output - GPIO 2 - State

"; + return buttons; + } + return String(); +} + +String outputState(){ + if(digitalRead(output)){ + return "checked"; + } + else { + return ""; + } + return ""; +} + +void setup(){ + // Serial port for debugging purposes + Serial.begin(115200); + + pinMode(output, OUTPUT); + digitalWrite(output, LOW); + pinMode(buttonPin, INPUT); + + // Connect to Wi-Fi + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(1000); + Serial.println("Connecting to WiFi.."); + } + + // Print ESP 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 /update?state= + server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) { + String inputMessage; + String inputParam; + // GET input1 value on /update?state= + if (request->hasParam(PARAM_INPUT_1)) { + inputMessage = request->getParam(PARAM_INPUT_1)->value(); + inputParam = PARAM_INPUT_1; + digitalWrite(output, inputMessage.toInt()); + ledState = !ledState; + events.send(String(digitalRead(output)).c_str(),"output_state",millis()); + + } + else { + inputMessage = "No message sent"; + inputParam = "none"; + } + Serial.println(inputMessage); + request->send(200, "text/plain", "OK"); + }); + + // Send a GET request to /state + server.on("/state", HTTP_GET, [] (AsyncWebServerRequest *request) { + request->send(200, "text/plain", String(digitalRead(output)).c_str()); + }); + + events.onConnect([](AsyncEventSourceClient *client){ + if(client->lastId()){ + Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId()); + } + // send event with message "hello!", id current millis + // and set reconnect delay to 1 second + client->send("hello!",NULL,millis(),10000); + }); + server.addHandler(&events); + + // Start server + server.begin(); +} + +void loop() { + static unsigned long lastEventTime = millis(); + static const unsigned long EVENT_INTERVAL_MS = 5000; // ms between heartbeat events + // read the state of the switch into a local variable: + int reading = digitalRead(buttonPin); + + // check to see if you just pressed the button + // (i.e. the input went from LOW to HIGH), and you've waited long enough + // since the last press to ignore any noise: + + // If the switch changed, due to noise or pressing: + if (reading != lastButtonState) { + // reset the debouncing timer + lastDebounceTime = millis(); + } + + if ((millis() - lastDebounceTime) > debounceDelay) { + // whatever the reading is at, it's been there for longer than the debounce + // delay, so take it as the actual current state: + + // if the button state has changed: + if (reading != buttonState) { + buttonState = reading; + + // only toggle the LED if the new button state is HIGH + if (buttonState == HIGH) { + ledState = !ledState; + digitalWrite(output, ledState); + events.send(String(digitalRead(output)).c_str(),"output_state",millis()); + } + } + } + + // set the LED: + digitalWrite(output, ledState); + + if ((millis() - lastEventTime) > EVENT_INTERVAL_MS) { + events.send("ping",NULL,millis()); + lastEventTime = millis(); + } + + // save the reading. Next time through the loop, it'll be the lastButtonState: + lastButtonState = reading; +} diff --git a/Projects/ESP/ESP_Web_Server_Physical_Button_WS.ino b/Projects/ESP/ESP_Web_Server_Physical_Button_WS.ino new file mode 100644 index 00000000..1d69b766 --- /dev/null +++ b/Projects/ESP/ESP_Web_Server_Physical_Button_WS.ino @@ -0,0 +1,223 @@ +#include "Arduino.h" +/********* + Rui Santos + Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-web-server-physical-button/ + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + *********/ + +// Import required libraries +#ifdef ESP32 +#include +#include +#else +#include +#include +#endif +#include + +// Replace with your network credentials +const char *ssid = "REPLACE_WITH_YOUR_SSID"; +const char *password = "REPLACE_WITH_YOUR_PASSWORD"; + +const char *PARAM_INPUT_1 = "state"; + +const int output = 27; +const int buttonPin = 4; + +// Variables will change: +int ledState = LOW; // the current state of the output pin +int buttonState; // the current reading from the input pin +int lastButtonState = LOW; // the previous reading from the input pin + +// the following variables are unsigned longs because the time, measured in +// milliseconds, will quickly become a bigger number than can be stored in an int. +unsigned long lastDebounceTime = 0; // the last time the output pin was toggled +unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers + +// Create AsyncWebServer object on port 80 +AsyncWebServer server(80); +AsyncWebSocket ws("/ws"); + +const char index_html[] PROGMEM + = R"rawliteral( + + + ESP Web Server + + + + +

ESP Web Server

+

Output - GPIO 2 - State

+ + + +)rawliteral"; + + +void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, + AwsEventType type, void *arg, uint8_t *data, size_t len) { + if (type == WS_EVT_CONNECT) { + //client connected + Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); + client->printf("%d", !digitalRead(output)); + client->ping(); + } else if (type == WS_EVT_DISCONNECT) { + //client disconnected + Serial.printf("ws[%s][%u] disconnect\n", server->url(), + client->id()); + } else if (type == WS_EVT_ERROR) { + //error was received from the other end + Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), + *((uint16_t*) arg), (char*) data); + } else if (type == WS_EVT_PONG) { + //pong message was received (in response to a ping request maybe) + Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, + (len) ? (char*) data : ""); + } else if (type == WS_EVT_DATA) { + //data packet + AwsFrameInfo *info = (AwsFrameInfo*) arg; + if (info->final && info->index == 0 && info->len == len) { + //the whole message is in a single frame and we got all of it's data + Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), + client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", + info->len); + if (info->opcode == WS_TEXT) { + data[len] = 0; + int command = atoi((char*)data); + Serial.printf("%s\n", (char*) data); + ledState = !command; + digitalWrite(output, ledState); + server->printfAll("%d", !digitalRead(output)); + } + } + } +} + +void setup() { + // Serial port for debugging purposes + Serial.begin(115200); + + pinMode(output, OUTPUT); + digitalWrite(output, LOW); + pinMode(buttonPin, INPUT); + + // Connect to Wi-Fi + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(1000); + Serial.println("Connecting to WiFi.."); + } + + // Print ESP 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); + }); + + ws.onEvent(onWsEvent); + server.addHandler(&ws); + + // Start server + server.begin(); +} + +void loop() { + static unsigned long lastWsCleanupTime = millis(); + static const unsigned long WS_CLEANUP_INTERVAL_MS = 5000; // ms between WebSocket cleanup + // read the state of the switch into a local variable: + int reading = digitalRead(buttonPin); + + // check to see if you just pressed the button + // (i.e. the input went from LOW to HIGH), and you've waited long enough + // since the last press to ignore any noise: + + // If the switch changed, due to noise or pressing: + if (reading != lastButtonState) { + // reset the debouncing timer + lastDebounceTime = millis(); + } + + if ((millis() - lastDebounceTime) > debounceDelay) { + // whatever the reading is at, it's been there for longer than the debounce + // delay, so take it as the actual current state: + + // if the button state has changed: + if (reading != buttonState) { + buttonState = reading; + + // only toggle the LED if the new button state is HIGH + if (buttonState == HIGH) { + ledState = !ledState; + digitalWrite(output, ledState); + ws.printfAll("%d", !digitalRead(output)); + } + } + } + + // set the LED: + digitalWrite(output, ledState); + + if ((millis() - lastWsCleanupTime) > WS_CLEANUP_INTERVAL_MS) { + ws.cleanupClients(); + lastWsCleanupTime = millis(); + } + + // save the reading. Next time through the loop, it'll be the lastButtonState: + lastButtonState = reading; +}