My idea for that working was create a checkbox that is acting as a button with an onclick event and at the same time indicating the status. Since i use a simple GET on the route "/toggle" of my server i used a XMLHttpRequest to have the checkbox just basically "touch" it to not have a navigation event in the browser. That works (more or less) fine to switch the led on or off from the browser. I can't seem to wrap my head around the other way, though.
my sketch so far:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>
#define RELAY 5
#define BUTTON 4
ESP8266WebServer server;
char* ssid = "xxxxxx";
char* password = "xxxxxxx";
bool currentState = false;
bool lastButtonState = false;
bool relayState = false;
const bool pressedState = 0;
const char *website =
#include "website.h"
;
void handleRoot() {
server.send ( 200, "text/html", website );
}
void handlePhysicalButton() {
currentState = digitalRead(BUTTON);
if (currentState != lastButtonState) {
lastButtonState = currentState;
if (currentState == pressedState) {
relayState = !relayState;
}
digitalWrite(RELAY, relayState);
}
delay(50); //poor mans debounce
server.send ( 200, "text/html", "" );
}
void handleWebButton() {
relayState = !relayState;
digitalWrite(RELAY, relayState);
Serial.print("Web button pressed!\n");
}
void setup() {
char HostName[32];
sprintf(HostName, "Narfel-%06X", ESP.getChipId()); //create hostname name+chip-id
WiFi.mode(WIFI_STA);
WiFi.hostname(HostName);
Serial.begin(115200);
pinMode(BUTTON, INPUT_PULLUP);
pinMode(RELAY, OUTPUT);
Serial.print("(Re)booting ");
Serial.printf("%s, ChipID: ", HostName);
Serial.println(ESP.getChipId());
// ======================================= wifi =====================
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
Serial.println(WiFi.localIP());
// ======================================= webserver ================
server.on ("/", handleRoot);
server.on("/toggle", handleWebButton);
server.begin();
// ======================================= OTA ======================
ArduinoOTA.setPassword((const char *)"xxxxxxx");
ArduinoOTA.onStart([]() {
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
Serial.printf("Done!");
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
}
void loop() {
ArduinoOTA.handle();
server.handleClient();
handlePhysicalButton();
}
Website.h:
R"0(
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title></title>
</head>
<body>
<script type="text/javascript">
function handleClick() {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/toggle');
xhr.send('');
}
</script>
<div class="switch">
<input type="checkbox" onclick="handleClick()">
</div>
</body>
</html>
)0"