1

I started my first project with the ESP8266.

It's a Temperature Monitor which shows the data on a webserver.

Since I don't want to refresh the page manually to get the new data, I'm using HTTP requests to display it.

I'm sending 3 different requests, one for the current temperature, one for the highest and one for the lowest.

The problem i'm facing is, that the data won't refresh simultaneously, though I am sending all of those at the same time.

That's the code that's sending the requests:

<script>
    function getCurrent() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("current").innerHTML =
        this.responseText;
      }
    };
    xhttp.open("GET", "readCurrent", true);
    xhttp.send();
    }

    function getHigh() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("high").innerHTML =
        this.responseText;
      }
    };
    xhttp.open("GET", "readHigh", true);
    xhttp.send();
    }

    function getLow() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        document.getElementById("low").innerHTML =
        this.responseText;
      }
    };
    xhttp.open("GET", "readLow", true);
    xhttp.send();
    }

    setInterval(function() {
      getHigh();
      getLow();
      getCurrent();
    }, 2000);
</script>

And that's the code handling them:

float temp;
float hoechst;
float tiefst;

void handleRoot() {
 String s = MAIN_page; //Read HTML contents
 server.send(200, "text/html", s); //Send web page
}

void handleCurrent() {
  float t = temp;
  server.send(200, "text/plane", String(t));
}

void handleHigh() {
  float high = hoechst;
  server.send(200, "text/plane", String(high));
}

void handleLow() {
  float low = tiefst;
  server.send(200, "text/plane", String(low));
}

void setup() {
  [...]
  server.on("/", handleRoot);
  server.on("/readCurrent", handleCurrent);
  server.on("/readHigh", handleHigh);
  server.on("/readLow", handleLow);
  [...]
}

The Loop is just updating the Temperatures with this function:

void updateTemperatures() {
  sensor.requestTemperatures();
  yield();
  float low = tiefst;
  float high = hoechst;
  float t = sensor.getTempCByIndex(0);
   if(t < low) {
    low = t;
    } else if(t > high) {
      high = t;
      }
   yield();
   temp = t;
   tiefst = low;
   hoechst = high;
  }

And handling the clients (server.handleClient())

So my Question: How can I update the data simultaneously, or is that even possible with the ESP8266?

jnkllnbrn
  • 15
  • 1
  • 4

2 Answers2

0

You update the data simultaneously by returning all three values in one request.

That would be the way to do it with any web server, let alone one running on an extremely limited processor like the ESP8266.

You can return all three values at once with code that looks something like this:

void handleAll() {
  String results_json = "{ \"temperature\": " + String(temp) + ",", +
                           "\"high\": " + String(hoechst) + "," +
                           "\"low\": " + String(tiefst) + " }";

  server.send(200, "application/json", results_json);
}

This composes a JSON object with all three values in it. JSON is "JavaScript Object Notation" and is very easy for Javascript to put together and take apart.

You'd also need to update your ESP8266 web server code to add

server.on("/readAll", handleAll);

With this change you can eliminate the other three /read handlers.

And you'd need to update your Javascript. You'd just need to do one call in Javascript, convert the returned text to a Javascript object and read each of the three values from it to set the elements in the DOM. This is something jQuery can so trivially for you.

And, it's 'text/plain', not 'text/plane'.

You might also check out jQuery - it will greatly simplify your Javascript code.

romkey
  • 6,218
  • 3
  • 16
  • 12
  • I'm really sorry if that is or sounds stupid, but I'm actually complete new to this topic, but how can I return all the data in one request, or rather how can i then place each data in another text field on my page? The only thing that I can think of is to put the data in a json file, and then extract the json data to each text field client side. Is there any prettier solution to this? – jnkllnbrn Mar 02 '19 at 23:42
  • JSON is the prettier solution - it's the "correct" way to do this. I overexplained in the update to the answer for other people who may come along and not know what JSON is. – romkey Mar 03 '19 at 00:29
  • I'd like to mention that you missed the commas between the data names in the json result. But with that it works just fine. – jnkllnbrn Mar 03 '19 at 12:49
0

Simply put: You can't update the data simultaneously because there's only one CPU core. Also, you should design with economy in mind, you wanted to have three transactions to get a few numbers... One of the simplest forms of database is CSV, or "Comma-Separated Values"; essentially: values separated by commas.

Knowing the order your temperatures are going to be in the list (low, current, high), you can simply create a new variable, or concatenate your variables in the statement that outputs the data, that's low "," current "," high and that would return you something like -1.23455,23.53556,37.23432 that you can easily split into three by looking for the commas, and using string operators.

Now you can get your three values from a single transaction from the low-spec device!

Good luck! : )

  • At first, thanks for the explanation on why it won't work, that's really interesting. Now i got a question, what's faster, put the data to one string and split it clientside, or create an object string and decode that object clientside (ref. JSON) – jnkllnbrn Mar 07 '19 at 22:55