Sari la conținut
ELFORUM - Forumul electronistilor

Autoupdate web server date senzori


XAN77

Postări Recomandate

La mulți ani dragi colegi

 

Am o problemă care mă enervează deja la 3 proiecte ce le am în uz prin casă.

Sunt niște web servere cu esp8266 cu date de la senzori. Am preluat inițial un cod de pe siteul randomnerdtutorial ce era un exemplu de webserver cu un singur senzor și am duplicat tot ce am crezut eu de cuviință pentru a avea 2 senzori. Problema este că în browser, atât pe pc cât și pe telefon, datele primului senzor cel din codul original, se actualizează singure la câteva secunde până în 10, dar datele senzorului adăugat de mine nu se actualizează decât dacă dau eu refresh în browser. Nu înțeleg ce nu am modificat bine sau ce trebuie să fac ca să se actualizeze toți senzorii la fel.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com  
*********/

// Import required libraries
#ifdef ESP32
  #include <WiFi.h>
  #include <ESPAsyncWebServer.h>
#else
  #include <Arduino.h>
  #include <ESP8266WiFi.h>
  #include <Hash.h>
  #include <ESPAsyncTCP.h>
  #include <ESPAsyncWebServer.h>
  #include <AsyncElegantOTA.h>
#endif
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is connected to GPIO 4
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

// Variables to store temperature values
String temperatureF = "";
String temperatureC = "";
String temperatureF2 = "";
String temperatureC2 = "";

// Timer variables
unsigned long lastTime = 0;  
unsigned long timerDelay = 2000;

// Replace with your network credentials
const char* ssid = "........";
const char* password = ".........";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

String readDSTemperatureC() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);

  if(tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

String readDSTemperatureF() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempF = sensors.getTempFByIndex(0);

  if(int(tempF) == -196){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Fahrenheit: ");
    Serial.println(tempF);
  }
  return String(tempF);
}

String readDSTemperatureC2() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC2 = sensors.getTempCByIndex(1);

  if(tempC2 == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC2); 
  }
  return String(tempC2);
}

String readDSTemperatureF2() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempF2 = sensors.getTempFByIndex(1);

  if(int(tempF2) == -196){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Fahrenheit: ");
    Serial.println(tempF2);
  }
  return String(tempF2);
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP DS18B20 Server</h2>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Celsius</span> 
    <span id="temperaturec">%TEMPERATUREC%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Fahrenheit</span>
    <span id="temperaturef">%TEMPERATUREF%</span>
    <sup class="units">&deg;F</sup>
  </p>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Celsius2</span> 
    <span id="temperaturec2">%TEMPERATUREC2%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Fahrenheit2</span>
    <span id="temperaturef2">%TEMPERATUREF2%</span>
    <sup class="units">&deg;F</sup>
  </p>  
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturec").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturec", true);
  xhttp.send();
}, 2000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturef").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturef", true);
  xhttp.send();
}, 2000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturec2").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturec2", true);
  xhttp.send();
}, 2000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturef2").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturef2", true);
  xhttp.send();
}, 2000) ;
</script>
</html>)rawliteral";
// Replaces placeholder with DS18B20 values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return temperatureC;
  }
  else if(var == "TEMPERATUREF"){
    return temperatureF;
  }
  else if(var == "TEMPERATUREC2"){
    return temperatureC2;
  }
  else if(var == "TEMPERATUREF2"){
    return temperatureF2;
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.println();
  
  // Start up the DS18B20 library
  sensors.begin();

  temperatureC = readDSTemperatureC();
  temperatureF = readDSTemperatureF();
  temperatureC2 = readDSTemperatureC2();
  temperatureF2 = readDSTemperatureF2();

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  
  // 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);
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temperatureC.c_str());
  });
  server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temperatureF.c_str());
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temperatureC2.c_str());
  });
  server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temperatureF2.c_str());
  });  
  AsyncElegantOTA.begin(&server); // Start ElegantOTA
  server.begin();                 // Start server
}
 
void loop(){
  if ((millis() - lastTime) > timerDelay) {
    temperatureC = readDSTemperatureC();
    temperatureF = readDSTemperatureF();
    temperatureC2 = readDSTemperatureC2();
    temperatureF2 = readDSTemperatureF2();
    lastTime = millis();
  }  
}

 

codul original se găsește aici, e o pagină cu 3 exemple de cod, aceste de webserver este al treilea.

Link spre comentariu
  • Răspunsuri 6
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • XAN77

    3

  • Liviu M

    2

Zile populare

Top autori în acest subiect

Acum 1 oră, x_dadu a spus:
xhttp.open("GET", "/temperaturec2", true);

 

Acum 1 oră, x_dadu a spus:
server.on("/temperaturec",

trebuie sa modifici si aici "temperaturec2" si "...f2"
 

Link spre comentariu

Conform obiceiului, pentru ca ai primit deja raspunsul la intrebare, vin si eu cu despicatul firului.

Eu n-as fi facut cate doua functii de citire a temperaturii, ci as fi adaugat un parametru pentru selectia senzorului in functiile existente. Ar fi mai usor de intretinut, daca vrei sa modifici ceva, o faci o singura data, nu de doua ori.

Pentru temperatura in °C functia s-ar transforma in:

String readDSTemperatureC(uint8_t uiSensor) {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(uiSensor);

  if(tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

si va fi folosita in setup si loop:

  temperatureC = readDSTemperatureC(0);
  temperatureC2 = readDSTemperatureC(1);

Probabil se poate gasi o varianta "comuna" si pentru cele doua "grade", desi cred ca cel mai "cinstit" ar fi cu o functie care sa citeasca senzorii o singura data (sensors.requestTemperatures();) si sa "genereze" toate cele 4 valori de care ai nevoie. Asa cum e acum, pentru cele 4 valori afisate tu citesti de 4 ori ambii senzori.

 

Si pentru ca sunt bata la partea de html, daca as avea hardul necesar as incerca sa vad ce se intampla daca "comasez" cele 4 setInterval() intr-unul singur.

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturec").innerHTML = this.responseText;
      document.getElementById("temperaturef").innerHTML = this.responseText;
      document.getElementById("temperaturec2").innerHTML = this.responseText;
      document.getElementById("temperaturef2").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturec", true);
  xhttp.send();
  xhttp.open("GET", "/temperaturef", true);
  xhttp.send();
  xhttp.open("GET", "/temperaturec2", true);
  xhttp.send();
  xhttp.open("GET", "/temperaturef2", true);
  xhttp.send();
}, 2000) ;

 

Link spre comentariu

Vă mulțumesc pentru răspunsuri, întradevăr după ce am modificat acele 2 linii de la server.on .... a mers. Acest cod l-am pregătit special pentru postare, ca să fie cât mai asemănător cu cel original, că proiectele de care mă plâng eu sunt mult mai modificate. Am vrut să evidiențez numai problema respectivă. Oricum când am făcut acest cod azi am sesizat și corectat și alte greșeli ce le făceam dar am omis acele modificări. Va trebui să-mi modific proiectele acum. Normal eu splituiesc proiectul în mai multe fișiere cu declarațiile și definirea variabilelor întrun tab/file.h, codul siteului html într-altul, funcția setup altul etc

Da @Liviu M e mai optimizat cum zici, am preferat așa doar pentru această postare.

ce este acel 2000 (inițial era 10000) de la finele funcției setInternal ( function() {}, 2000 ) ? E cumva timpul de autorefresh ? Că am văzut că acel timp e oarecum variabil.

Am încercat varianta cu comasarea setInterval. Dar la primu autorefresh toate cele 4 valori devin identice și anume F2. dacă dau refresh manual, valorile apar corecte dar în câteva secunde la autoupdate iar sunt toate valoarea lui F2

Editat de x_dadu
Link spre comentariu
Acum 34 minute, Liviu M a spus:

Si pentru ca sunt bata la partea de html, daca as avea hardul necesar as incerca sa vad ce se intampla daca "comasez" cele 4 setInterval() intr-unul singur.

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturec").innerHTML = this.responseText;
      document.getElementById("temperaturef").innerHTML = this.responseText;
      document.getElementById("temperaturec2").innerHTML = this.responseText;
      document.getElementById("temperaturef2").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturec", true);
  xhttp.send();
  xhttp.open("GET", "/temperaturef", true);
  xhttp.send();
  xhttp.open("GET", "/temperaturec2", true);
  xhttp.send();
  xhttp.open("GET", "/temperaturef2", true);
  xhttp.send();
}, 2000) ;

Nu cred ca merge asa ca mai sus. La cine face referire "this" in acest caz ?
Poate prin folosirea de mai multe obiecte XMLHttpRequest: xhttp1, xhttp2...  Si definirea de events separate de tip onreadystatechange pentru fiecare.
Dar eu zic ca se complica inutil.

Editat de Vizitator
Link spre comentariu

M-am apucat să mdific proiectele mele ca să facă autoupdate la toate valorile din pagină, 2 le-am rezolvat deja la al treilea am mai mult de lucru că e diferită partea de web și vreau s-o fac în același stil. Acum modificând acele proiecte am constatat că eroarea mea principală era că nu duplicam corespunzător acea secvență cu setInterval. De, bizon.

Link spre comentariu
Acum 16 minute, Liviu.Mihaiu a spus:

Nu cred ca merge asa ca mai sus. La cine face referire "this" in acest caz ?

Speram ca fiecare sa se refere la documentul care le foloseste

document.getElementById("temperaturec")

da' se pare ca nu. Cum ziceam, la html mai am mult de studiat.

 

Acum 35 minute, x_dadu a spus:

ce este acel 2000 (inițial era 10000) de la finele funcției setInternal ( function() {}, 2000 ) ? E cumva timpul de autorefresh ?

Da, asa cum ii zice numele, seteaza un interval. In cazul tau de refresh.

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări