Passing Variables into HTML for initial Load/Send - server.on("/",server.send...

Hi, Grateful for some direction on this project;

Goal: ESP8285 is controlling 4 power sockets on a power board. The power/relays can be switched by;

  1. Push-button on the power board
  2. Home Automation system (HASSIO) via MQTT
  3. Web Page served from the ESP8285

Problem: When a browser loads the initial HTML Page it’s important the web-buttons reflect the current state of the pins driving the power/relays.

I can read the pin state when the button is ‘clicked’ but I want to know the state BEFORE toggling the switch.

I’ve ‘stolen’ the code from various sources and it’s a ‘work in progress’, but you will see what I am trying to do.
Please don’t hammer me for all the Strings - once I get it working I plan to change them to char arrays - it a work in progress… I’m also trying to get my head around Javascript and AJAX as you can tell.

This doesn’t work, grateful for any suggestions.

String html_2 = "    <td> <input type='button' id='LED1_button' value="msg[2]"class='red' onclick='testing(this.id,1)' />  </td>";
/*
 * 20200705 Counting button presses
 * Next: move 'counting' to a function and use it to toggle relays - DONE!
 * 20200707 Long press to switch all relays FF
 * 20200711 HTML Code
 * 20200712 Adding Javascript to HTML
 * 20200713 Strugging with AJAX - look at webserver_html_js.ino
*/

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>

#define mqtt_server "10.16.15.161"
#define MQTT_topic "testing/"
#define arlec_topic "testing/arlec" 
#define relay1 5 
#define relay2 4
#define relay3 13
#define relay4 12
#define mainButton 3
#define mainLED 1


WiFiClient arlecClient;
PubSubClient client(arlecClient);


MDNSResponder mdns;

// Replace with your network credentials
const char* ssid = "Home WiFi";
const char* password = "Password";
const char* deviceName = "Arlec_test";
const unsigned long interval = 3000; 
unsigned long currentMillis = 0;
unsigned long startTimer = 0;
unsigned long longPressTimer = 0; 
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 1;     // previous state of the button
bool counting = false;
bool pressTimer = false;
char msg[5] = "OFF";

String request = "";
String header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";

String html_1 = R"=====(
<!DOCTYPE html>
<html>
 <head>
 <meta name='viewport' content='width=device-width, initial-scale=1.0'/>
 <meta charset='utf-8'>
 <style>
  body {font-size:140%; } 
  #main {display: table; margin: auto;  padding: 0 5px 0 5px;  } 
  h2 {text-align:center; } 
  input[type="button"] { width: 4em; font-size: 120%; }
  .green { background-color: #50FF50;  }
  .red   { background-color: #FF5050;  }  
  table {width: 100%; }
 </style>

<script>
    function switchLED(buttonID,LED) 
  {
   var button_text = document.getElementById(buttonID).value;
     if (button_text=="OFF")
     {
       document.getElementById(buttonID).value = "ON";
       document.getElementById(buttonID).style.background = "#50FF50";
       ajaxLoad('L' + LED + '1'); 
     document.getElementById("p2").innerHTML = 'L' + LED + '1';
     }
     else
     {
       document.getElementById(buttonID).value = "OFF";
       document.getElementById(buttonID).style.background = "#FF5050";
       ajaxLoad('L' + LED + '0');
     document.getElementById("p2").innerHTML = 'L' + LED + '0';
   
    }
  document.getElementById("p1").innerHTML = buttonID;
  }

  var ajaxRequest = null;
  if (window.XMLHttpRequest)  { ajaxRequest =new XMLHttpRequest(); }
  else                        { ajaxRequest =new ActiveXObject("Microsoft.XMLHTTP"); }


  function ajaxLoad(ajaxURL)
  {
    if(!ajaxRequest){ alert("AJAX is not supported."); return; }
    
    ajaxRequest.open("GET",ajaxURL,true);
    ajaxRequest.onreadystatechange = function()
    {
      if(ajaxRequest.readyState == 4 && ajaxRequest.status==200)
      {
        var ajaxResult = ajaxRequest.responseText;
      }
    }
    ajaxRequest.send();
  }
  
  function testing(buttonID, plug)
  {
    console.log("button was clicked!");
    var button_state = document.getElementById(buttonID).value;
    console.log(button_state);
    var dataLoad = (plug+"/"+button_state);
    console.log(dataLoad);
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("LED1_button").innerHTML = this.responseText;
        console.log(this.responseText);
        document.getElementById(buttonID).value = "ON";           //problem here
        document.getElementById(buttonID).style.background = "#50FF50";
        
      }
    };
    
    xhttp.open("GET", "toggle?relayCMD="+dataLoad, true);
    console.log("toggle/",dataLoad);
    xhttp.send();
  };
   
</script>

 <title>ARLEC Web Control</title>
</head>
<body>
 <div id='main'>
  <h2>LED Control</h2>
  <table id = "controls">
   <tr>
    <td width="70%">LED 1</td>
)=====";

String html_2 = "    <td> <input type='button' id='LED1_button' value="msg[2]"class='red' onclick='testing(this.id,1)' />  </td>";

String html_3 = R"=====(
   </tr>
   <tr>
    <td width="70%">LED 2</td>
)=====";

String html_4 = "    <td> <input type='button' id='LED2_button' value='OFF' class='red' onclick='switchLED(this.id,2)' />  </td>";

String html_5 = R"=====(
   </tr>
   <tr>
    <td width="70%">LED 3</td>
)=====";    

String html_6 = "    <td> <input type='button' id='LED3_button' value='OFF' class='red' onclick='switchLED(this.id,3)' />  </td>";

String html_7 = R"=====(
   </tr>
   <tr>
    <td width="70%">LED 4</td>
)====="; 

String html_8 = "    <td> <input type='button' id='LED4_button' value='OFF' class='red' onclick='switchLED(this.id,4)' />  </td>"; 

String html_9 = R"=====(
   </tr>
  </table>
  <p id="p1">Button ID</p>
  <p id="p2">LED number</p>
 </div>
</body>
</html>
 
)=====";

//Static IP address configuration
IPAddress staticIP(10, 16, 15, 79); //ESP static ip
IPAddress gateway(10, 16, 15, 150);   //IP Address of your WiFi Router (Gateway)
IPAddress subnet(255, 255, 255, 0);  //Subnet mask
IPAddress dns(10, 16, 15, 150);  //DNS
ESP8266WebServer server(80);



void setup_web_server(){
  server.on("/",[](){server.send(200,"text/html", header+html_1+html_2+html_3+html_4+html_5+html_6+html_7+html_8+html_9);});
  server.on("/toggle",testing2);
 
  server.begin(); //Start the server
  Serial.println("Server listening");
}

void testing2(){
  
  String test = server.arg("relayCMD");
  test.toCharArray(msg, 5);
  client.publish(arlec_topic, "testing2");
  client.publish(arlec_topic, msg);
  processMsg();
  String led_state = digitalRead(relay1) ? "ON" : "OFF";
  server.send(200, "text/plane", led_state); //Send web page
}

void getLEDState()
{
  
  plug1(!digitalRead(relay1));
  String led_state = digitalRead(relay1) ? "ON" : "OFF";
  server.send(200,"text/plain", led_state);
}

void setup(void){  
  //  Init

  Serial.begin(115200);
  pinMode(relay1, OUTPUT);
  digitalWrite(relay1, LOW);
  pinMode(relay2, OUTPUT);
  digitalWrite(relay2, LOW);
  pinMode(relay3, OUTPUT);
  digitalWrite(relay3, LOW);
  pinMode(relay4, OUTPUT);
  digitalWrite(relay4, LOW); 
  pinMode(mainLED, OUTPUT); 
  
  pinMode(mainButton, INPUT);
  setup_wifi();
  setup_web_server();
  setup_OTA();
  client.setServer(mqtt_server, 1883);
  reconnect();
  client.setCallback(callback); 
  digitalWrite(mainLED, LOW);

}

void setup_OTA(){
}

void setup_wifi() {
}
  


// Callback function - Handles messages arrived on subscribed topic(s)
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++) {
    msg[i] = ((char)payload[i]);
  }
  msg[length] = ('\0');
  Serial.print(msg);
  Serial.println();
  client.publish(arlec_topic, msg);
  processMsg();
}

void processMsg(){
  
  if (strcmp(msg,"1/ON")==0){
    plug1(HIGH);
  }
  if (strcmp(msg,"1/OFF")==0){
    plug1(LOW);
  }
  if (strcmp(msg,"2/ON")==0){
    plug2(HIGH);
  }
  if (strcmp(msg,"2/OFF")==0){
    plug2(LOW);
  }
  if (strcmp(msg,"3/ON")==0){
    plug3(HIGH);
  }
  if (strcmp(msg,"3/OFF")==0){
    plug3(LOW);
  }
  if (strcmp(msg,"4/ON")==0){
    plug4(HIGH);
  }
  if (strcmp(msg,"4/OFF")==0){
    plug4(LOW);
  }
  if (strcmp(msg,"LED/ON")==0){
    switchLED(LOW);
  }
  if (strcmp(msg,"LED/OFF")==0){
    switchLED(HIGH);
  }

}

void reconnect() {      
}
void plug2(bool x){
  digitalWrite(relay2, x);
  
}

void plug3(bool x){
  digitalWrite(relay3, x);
  
}

void plug4(bool x){
  digitalWrite(relay4, x);
  
}
void switchLED(bool x){
  digitalWrite(mainLED, x);
  
}

void button(){
}

void countPresses(){
}
void blinkLED(int y){
}

 
void loop(void){
  ArduinoOTA.handle();
  server.handleClient();
    if (!client.connected()) {
    reconnect();
  }
  client.loop();
  button();
  if (counting){
    countPresses();
  }
  server.handleClient(); //Handling of incoming HTML requests

}

I can read the pin state when the button is ‘clicked’ but I want to know the state BEFORE toggling the switch.

Why do you want to know the state?

if you want to read the pin, read it.
If you want to toggle, toggle!

e.g.

void digitalToggle(int pin){
  digitalWrite(pin, !digitalRead(pin));
}

Why do you want to know the state? [/quote]

Hi noiasca, if something crucial is plugged into the power outlet and the Web Page loads showing the wrong state I don't want to switch it off/on by mistake, so I want to know the state when web page initially loads.

OK - Imagine this: Grandma’s ventilator is plugged into socket 4 of the power board, If I browse to the ESP8285 controlling the board the Web page served up from ‘server.on(/)’ will show the power as “OFF” because that is the HTML.

<input type='button' id='LED1_button' value="OFF"class='red' onclick='testing(this.id,1)' />

If I hit the button to toggle the power I’ll get my inheritance early, but no Christmas cards from the rest of the family.

Is there a way to read the pin states and reflect them in the initial web page - or trigger a script that will update the relay status as soon as it is loaded. ie something that doesn’t require user intervention.

you can update the state of the outputs

either during sending out your HTML, or with AJAX/Javascript or with FetchAPI/Javascript

the later two option give you the possibility that the values could be updated also in a periodically.

This site is in German, but I guess you can see the necessary parts: https://werner.rothschopf.net/201809_arduino_esp8266_server_client_2.htm

Thanks Noiasca, that is a valuable resource. I found exactly what I needed in this video:

https://www.youtube.com/watch?v=4sDpcUEbtsA sending periodical updates between the client and server.

In case anyone else is looking for a similar solution. (Also I didn't realise 'on.server' could run multiple functions)

Great forum, thanks again!