prampec / IotWebConf

ESP8266/ESP32 non-blocking WiFi/AP web configuration Arduino library
MIT License
530 stars 140 forks source link

dynamically load sensor data into page, without refreshing? #219

Closed societyofrobots closed 3 years ago

societyofrobots commented 3 years ago

I'd like to use the webpage it creates to dynamically display feedback, like the value of a variable, without the page needing to constantly refresh.

Is there any easy way to do this?

edit: found this: http://www.martyncurrey.com/esp8266-and-the-arduino-ide-part-8-auto-update-webpage/

I'll update if I manage to get that working.

JonS9999 commented 3 years ago

I've had good luck with WebSockets on an ESP8266. I'm sorry I don't have an example handy (I'm not near my normal development PC), but you should be able to find a WebSockets library and some simple examples on the web. You can use WebSockets to push data to a client (browser) in real-time -- no need to do refreshes, etc. It works very well.

Give me a shout if you get stuck.

Good luck! :-)

prampec commented 3 years ago

What you are looking for is asynchronous web application. On the server side you create "pages" or entry points, that respond in JSON format. On the client side inside the browser you create special Javasript logic, that requests queries these entry points and dynamically modifies the HTML DOM. Search for term "AJAX"!

societyofrobots commented 3 years ago

Ok thanks!

Using your recommendation, I searched for "esp32 ajax example" and got it working in about 30 minutes using this sample code: https://circuits4you.com/2018/11/20/web-server-on-esp32-how-to-update-and-display-sensor-values/

societyofrobots commented 3 years ago

The above code had a problem in that it only let me transmit one value. I needed to transmit a range of values. I'm posting my new solution here for anyone else that needs it.

I basically copied this code: http://plnkr.co/edit/7DyTmdRdWSIRxx7ESLNv?p=preview&preview

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <h5>Messwerte</h5>
  <p>Analoger Pin 36: <span id='pin36'></span></p>
  <p>Analoger Pin 39: <span id='pin39'></span></p>
  <p>Analoger Pin 5: <span id='pin5'></span></p>

  <script>
    requestData(); // get intial data straight away 

    // request data updates every 5000 milliseconds
    setInterval(requestData, 5000);

    function requestData() {

      var xhr = new XMLHttpRequest();
      xhr.open('GET', 'sensors');

      xhr.onload = function() {
        if (xhr.status === 200) {

          if (xhr.responseText) { // if the returned data is not null, update the values

            var data = JSON.parse(xhr.responseText);

            document.getElementById("pin36").innerText = data.pin36;
            document.getElementById("pin39").innerText = data.pin39;
            document.getElementById("pin5").innerText = data.pin5;

          } else { // a problem occurred

            document.getElementById("pin36").innerText = "?";
            document.getElementById("pin39").innerText = "?";
            document.getElementById("pin5").innerText = "?";
          }
        } else {
          console.log('Request failed.  Returned status of ' + xhr.status);

          document.getElementById("pin36").innerText = "?";
          document.getElementById("pin39").innerText = "?";
          document.getElementById("pin5").innerText = "?";

        }
      };

      xhr.send();
    }

  </script>
</body>

</html>

And I constructed the JSON message as so:

  String v;
  v+="{\"pin36\": ";
  v+=val1;
  v+=", \"pin39\": ";
  v+=val2;
  v+=", \"pin5\": ";
  v+=val3;
  v+="}";

  server.send(200, "text/plane", v);