ESP8266 ESPAsyncWebServer обработка HTML

Вопрос или проблема

Я расширяю пример кода для WiFi-термометра функцией логгирования данных. Статус RTC и SD-карты будет отображаться в HTML-файле. В коде присутствуют заполнители для статуса RTC и SD-карты. Установленный процессор заменяет заполнители значениями, подготовленными MCU.

String statusRTC = "a";
String statusSD = "b";

Определены как глобальные.

Включения:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <Ticker.h>
#include "RTClib.h"

Чистый пример кода работает даже при отсутствии RTC и SD-карты. После добавления секций для RTC и SD соединение истекает. В мониторинге последовательного порта появляется ошибка (28), что означает доступ к недоступному адресу.

Смотрите секцию HTML, процессор, корневую секцию в настройках:

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: left;
     padding: 3px;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 2.0rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP8266 QDHTD Server</h2>
    <h3>RealtimeClocks</h3>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="dht-labels">Температура</span> 
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">&deg;C</sup>
  </p>

  <p>
    <i class="fas fa-tint" style="color:#00add6;"></i> 
    <span class="dht-labels">Влажность</span>
    <span id="humidity">%HUMIDITY%</span>
    <sup class="units"> pct</sup>
  </p>

  <!-- добавлено для отображения статуса RTC и SD-карты -->

  <p>
    <i class="fas fa-clock" style="color:#059e8a;"></i> 
    <span class="dht-labels">RTC____</span>    
    <span id="rtc">%STAT_RTC%</span>
  </p>

  <p>
    <i class="fas fa-sd-card" style="color:#059e8a;"></i> 
    <span class="dht-labels">Память</span> 
    <span id="sd_card">%STAT_SD%</span>
  </p>

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

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

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

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

</script>
</html>)rawliteral";

——————————-

Процессор:

// Заменяет заполнители значениями DHT
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(t);
  }
  else if(var == "HUMIDITY"){
    return String(h);
  }

  else if( var == "STAT_RTC"){
    if( rtc.isrunning()){
      statusRTC = "в порядке.";
      return(statusRTC);
    }
    else {
      statusRTC = "не работает";
      return(statusRTC);
    }
  }
else if( var == "STAT_SD"){
    bool avail =SD.exists("datalog.txt");
    if( avail== true){
      statusSD = "в порядке.";
      return(statusSD);
    }
    else {
      statusSD = "SD не работает";
      return(statusSD);
    }
  }

  return String();
}

———————

Корень в настройках:

  // Маршрут для корня / веб-страницы
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(t).c_str());
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(h).c_str());
  });

  server.on("/rtc", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", statusRTC.c_str());
  });

  server.on("/sd_card", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", statusSD.c_str());
  });

Поиск в интернете. Проверка на % в заполнительных значениях. Ссылка на HTML. Проверка правильности HTML на w3school

Ответ или решение

Для решения проблемы, с которой вы столкнулись при использовании библиотеки ESPAsyncWebServer на платформе ESP8266, необходимо учесть несколько ключевых моментов. Вы упомянули, что получаете исключение (28), указывающее на доступ к недопустимому адресу, когда добавляете секции для RTC и SD-карты. Давайте разберемся с возможными решениями этой проблемы.

1. Проверка статуса RTC и SD-карты

Первое, что следует сделать, — убедиться, что устройства RTC и SD-карты корректно инициализированы, и доступ к ним возможен. Это можно сделать в функции setup(), например:

if (!rtc.begin()) {
  Serial.println("RTC не найден");
}

if (!SD.begin()) {
  Serial.println("Не удалось инициализировать SD-карту");
}

2. Обновление кода процессора

Ваш код для замены плейсхолдеров в HTML-документе выглядит неплохо. Однако в функции processor вы не учитываете возможность, что при обращении к ним могут возникнуть ошибки. Также стоит добавить некоторые проверки.

String processor(const String& var) {
  if (var == "TEMPERATURE") {
    return String(t);
  } else if (var == "HUMIDITY") {
    return String(h);
  } else if (var == "STAT_RTC") {
    if (rtc.isrunning()) {
      statusRTC = "o.k.";
    } else {
      statusRTC = "не работает";
    }
    return statusRTC; // Статус RTC
  } else if (var == "STAT_SD") {
    bool avail = SD.exists("datalog.txt");
    if (avail) {
      statusSD = "o.k.";
    } else {
      statusSD = "Ошибка SD";
    }
    return statusSD; // Статус SD-карты
  }
  return String(); // В случае если переменная не совпадает
}

3. Корректное отображение статусов

В вашей HTML-странице отображаются статусы RTC и SD-карты. Убедитесь, что _rtc и _sd_card корректно обновляются:

setInterval(function () {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("rtc").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/rtc", true);
  xhttp.send();
}, 10000); // 10 секунд для обновления статуса RTC

setInterval(function () {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("sd_card").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/sd_card", true);
  xhttp.send();
}, 10000); // 10 секунд для обновления статуса SD-карты

4. Настройка маршрутов

Убедитесь, что маршруты настроены правильно и что они вызываются. Ваш код маршрутов выглядит хорошо, но добавьте проверки ошибок, если необходимо. Например, можно добавлять логгирование на сериал монитор для каждой из команд.

5. Дополнительные рекомендации

  • Убедитесь, что все библиотеки обновлены до последних версий, так как их стабильность может оказать влияние на функциональность.
  • Также проверьте настройки вашей сети и наличие других компонентов, которые могут вызывать помехи.
  • Не забывайте об управлении памятью. Поскольку вы используете массивы строк, следите за их длиной и объемом используемой памяти.

Следуя данным рекомендациям, вы сможете устранить проблему с обращением к недопустимым адресам и предоставить корректную информацию о статусах RTC и SD-карты на вашем веб-интерфейсе. Удачи в разработке вашего проекта на ESP8266!

Оцените материал
Добавить комментарий

Капча загружается...