Подключение DHT11 DHT22 AM2302 к ESP32 и отображение значений на веб-сервере

Подключение DHT11/DHT22 к ESP32 и отображение значений через веб-сервер

Подключение DHT11/DHT22 к ESP32 и отображение значений через веб-сервер

Вы когда-нибудь мечтали использовать мобильный телефон, планшет или компьютер для мониторинга температуры и влажности в доме, холодильной камере или винном погребе в любое время? Тогда этот IoT-проект может стать отличной отправной точкой!

В этом проекте ESP32 используется как управляющее устройство, которое подключается к существующей WiFi-сети и создаёт веб-сервер. Когда устройство подключается к этому веб-серверу, ESP32 считывает температуру и относительную влажность с датчика DHT11/DHT22 и отправляет данные в веб-браузер устройства с красивым интерфейсом. Интересно? Давайте начнём!

Есть несколько концепций, с которыми вам следует ознакомиться, прежде чем продолжить работу с этим руководством. Если какие-либо из приведённых ниже руководств вам незнакомы, рассмотрите возможность их предварительного изучения:

РЕКОМЕНДУЕМОЕ ЧТЕНИЕ

Подключение датчиков DHT11 и DHT22 к Arduino

Хотите отслеживать климат в теплице, создать систему управления хьюмидором или следить за температурой и влажностью для метеостанции?…

/lastminuteengineers/dht11-dht22-arduino-tutorial/index
Установка платы ESP32 в Arduino IDE

Микроконтроллер ESP32 быстро стал одной из самых популярных плат среди любителей, инженеров и людей, интересующихся Интернетом вещей (IoT)…

/lastminuteengineers/esp32-arduino-ide-tutorial/index
Создание простого веб-сервера на ESP32 в Arduino IDE

ESP32 стал одним из самых популярных микроконтроллеров в мире IoT — и не без причины. Он мощный, доступный и имеет встроенные…

/lastminuteengineers/creating-esp32-web-server-arduino-ide/index

Почему не использовать встроенный датчик температуры ESP32?

ESP32 действительно имеет встроенный датчик температуры с диапазоном измерений от -40°C до 125°C. Этот датчик температуры вырабатывает напряжение, пропорциональное температуре, которое затем преобразуется в цифровую форму внутренним аналого-цифровым преобразователем.

Согласно даташиту ESP32, проблема этого датчика температуры заключается в том, что смещение варьируется от чипа к чипу из-за технологического разброса. На измерения температуры также влияет тепло, выделяемое схемой Wi-Fi. В результате внутренний датчик температуры подходит только для приложений, которые обнаруживают изменения температуры, а не абсолютные значения температуры.

Подключение датчика DHT11/DHT22 к ESP32

Подключение датчика DHT11/DHT22 к ESP32 довольно простое. Начните с размещения ESP32 на макетной плате, убедившись, что каждая сторона платы находится на разных сторонах макетной платы.

Разместите датчик на макетной плате рядом с ESP32. Подключите вывод VCC датчика к выводу 3.3V ESP32, а землю — к земле. Подключите вывод Data датчика к выводу D4 ESP32. Наконец, добавьте подтягивающий резистор 10 кОм между VCC и линией данных, чтобы удерживать её в состоянии HIGH для корректной связи между датчиком и ESP32.

На изображении ниже показана схема подключения.

Схема подключения датчика температуры и влажности DHT22 к ESP32

Подключение датчика температуры и влажности DHT22 к ESP32

Схема подключения датчика температуры и влажности DHT11 к ESP32

Подключение датчика температуры и влажности DHT11 к ESP32

Установка библиотеки для датчика DHT

Чтобы начать считывать данные с датчика, вам необходимо установить библиотеку DHT sensor. Она доступна через менеджер библиотек Arduino.

Чтобы установить библиотеку, перейдите в Sketch > Include Library > Manage Libraries… Дождитесь, пока менеджер библиотек загрузит индекс библиотек и обновит список установленных библиотек.

Установка библиотеки Arduino — выбор Manage Libraries в Arduino IDE

Отфильтруйте поиск, введя „DHT sensor“. Найдите DHT sensor library от Adafruit. Нажмите на эту запись и затем выберите Install.

Установка библиотеки Adafruit DHT

Библиотека DHT sensor использует бэкенд поддержки Adafruit Sensor. Поэтому найдите Adafruit Unified Sensor в менеджере библиотек и установите её тоже.

Установка библиотеки Adafruit Unified Sensor

Создание веб-сервера ESP32 в режиме WiFi Station (STA)

Давайте перейдём к самому интересному!

Как следует из заголовка, мы настроим веб-сервер ESP32 в режиме Station (STA) для обслуживания веб-страниц любому подключённому клиенту в существующей сети.

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

const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

Когда закончите, попробуйте загрузить скетч, а затем мы подробно его разберём.

#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"

// Uncomment one of the lines below for whatever DHT sensor type you're using!
//#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

/*Put your SSID & Password*/
const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

WebServer server(80);

// DHT Sensor
uint8_t DHTPin = 4;

// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);

float Temperature;
float Humidity;

void setup() {
  Serial.begin(115200);
  delay(100);

  pinMode(DHTPin, INPUT);

  dht.begin();

  Serial.println("Connecting to ");
  Serial.println(ssid);

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");

}
void loop() {

  server.handleClient();

}

void handle_OnConnect() {

 Temperature = dht.readTemperature(); // Gets the values of the temperature
  Humidity = dht.readHumidity(); // Gets the values of the humidity
  server.send(200, "text/html", SendHTML(Temperature,Humidity));
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(float Temperaturestat,float Humiditystat){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>ESP32 Weather Report</title>\n";
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
  ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<div id=\"webpage\">\n";
  ptr +="<h1>ESP32 Weather Report</h1>\n";

  ptr +="<p>Temperature: ";
  ptr +=(int)Temperaturestat;
  ptr +="°C</p>";
  ptr +="<p>Humidity: ";
  ptr +=(int)Humiditystat;
  ptr +="%</p>";

  ptr +="</div>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

Доступ к веб-серверу

После загрузки скетча откройте монитор порта на скорости 115200 бод и нажмите кнопку RESET на ESP32. Если всё в порядке, он отобразит динамический IP-адрес, полученный от вашего роутера, а также сообщение «HTTP server started».

Вывод монитора порта веб-сервера ESP32 в режиме Station — сервер запущен

Далее запустите браузер и перейдите по IP-адресу, отображённому в мониторе порта. ESP32 должен отдать веб-страницу с текущей температурой и относительной влажностью.

Отображение температуры и влажности DHT11 DHT22 AM2302 на веб-сервере ESP32 — без CSS

Подробное объяснение кода

Скетч начинается с подключения библиотеки WiFi.h. Эта библиотека содержит методы, специфичные для ESP32, которые мы используем для подключения к сети. Далее мы подключаем библиотеку WebServer.h, которая содержит некоторые методы, помогающие нам настроить сервер и обрабатывать входящие HTTP-запросы, не беспокоясь о низкоуровневых деталях реализации. Наконец, мы подключаем библиотеку DHT.h.

#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"

Далее мы указываем тип используемого датчика DHT. Раскомментируйте соответствующую строку ниже!

//#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

Поскольку мы настраиваем веб-сервер ESP32 в режиме Station (STA), он будет присоединяться к существующей WiFi-сети. Поэтому нам нужно указать SSID и пароль.

/*Put your SSID & Password*/
const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

Далее мы создаём объект библиотеки WebServer, чтобы получить доступ к её функциям. Конструктор этого объекта принимает в качестве параметра порт, на котором сервер будет слушать. Поскольку HTTP по умолчанию использует порт 80, мы будем использовать это значение. Это позволяет подключаться к серверу без указания порта в URL.

// declare an object of WebServer library
WebServer server(80);

Далее мы определяем номер GPIO-пина на ESP32, к которому подключён вывод Data нашего датчика, и создаём объект DHT. Таким образом, мы можем получить доступ к функциям, специфичным для библиотеки DHT.

// DHT Sensor
uint8_t DHTPin = 4;

// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);

Определены две переменные типа float: Temperature и Humidity.

float Temperature;
float Humidity;

Внутри функции Setup()

В функции setup мы настраиваем наш веб-сервер. Сначала мы устанавливаем последовательное соединение для отладки и настраиваем GPIO-пин на работу в режиме INPUT. Также мы инициализируем объект DHT.

Serial.begin(115200);
delay(100);

pinMode(DHTPin, INPUT);

dht.begin();

Затем мы используем функцию WiFi.begin() для подключения к WiFi-сети. Функция принимает SSID (имя сети) и пароль в качестве параметров.

Serial.println("Connecting to ");
Serial.println(ssid);

//connect to your local wi-fi network
WiFi.begin(ssid, password);

Пока ESP32 пытается подключиться к сети, мы можем использовать функцию WiFi.status() для проверки состояния подключения.

//check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }

После подключения к сети функция WiFi.localIP() используется для вывода IP-адреса, назначенного ESP32.

Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

Для обработки входящих HTTP-запросов нам нужно указать, какой код должен выполняться при обращении к определённому URL. Для этого мы используем метод .on(). Этот метод принимает два параметра: относительный URL-путь и имя функции, которая будет выполняться при посещении этого URL.

Приведённый ниже код указывает, что когда сервер получает HTTP-запрос по корневому пути (/), он вызовет функцию handle_OnConnect(). Важно отметить, что указанный URL является относительным путём.

server.on("/", handle_OnConnect);

Мы не указали, что сервер должен выдавать, если клиент запрашивает URL, не указанный через server.on(). В ответ он должен выдать ошибку 404 (Page Not Found). Для этого мы используем метод server.onNotFound().

server.onNotFound(handle_NotFound);

Теперь для запуска сервера мы вызываем метод begin() объекта server.

server.begin();
Serial.println("HTTP server started");

Внутри функции Loop()

Фактическая обработка входящих HTTP-запросов происходит в функции loop. Для этого мы используем метод handleClient() объекта server.

server.handleClient();

Теперь нам нужно написать функцию handle_OnConnect(), которую мы ранее привязали к корневому (/) URL через server.on. Мы начинаем эту функцию с чтения значений температуры и влажности с датчика.

Мы используем метод send для ответа на HTTP-запрос. Хотя метод может вызываться с различными аргументами, в простейшей форме он требует код HTTP-ответа, тип содержимого и само содержимое.

Первый параметр, который мы передаём методу send, — это код 200 (один из кодов состояния HTTP), соответствующий ответу OK. Затем мы указываем тип содержимого как «text/html», и, наконец, передаём пользовательскую функцию SendHTML(), которая генерирует динамическую HTML-страницу с показаниями температуры и влажности.

void handle_OnConnect()
{
  Temperature = dht.readTemperature(); // Gets the values of the temperature
  Humidity = dht.readHumidity(); // Gets the values of the humidity
  server.send(200, "text/html", SendHTML(Temperature,Humidity));
}

Аналогично мы пишем функцию для обработки страницы ошибки 404.

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

Отображение HTML-веб-страницы

Каждый раз, когда веб-сервер ESP32 получает запрос от веб-клиента, функция sendHTML() генерирует веб-страницу. Она просто объединяет HTML-код в одну длинную строку и возвращает её функции server.send(), которую мы обсуждали ранее. Функция принимает показания температуры и влажности в качестве параметров для динамической генерации HTML-содержимого.

Первый текст, который вы всегда должны отправлять, — это объявление <!DOCTYPE>, указывающее, что мы отправляем HTML-код.

String SendHTML(float Temperaturestat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";

Мета-элемент <meta> viewport делает веб-страницу адаптивной, обеспечивая хорошее отображение на всех устройствах. Тег title определяет заголовок страницы.

ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>ESP32 Weather Report</title>\n";

Стилизация веб-страницы

Далее у нас есть CSS для стилизации общего внешнего вида веб-страницы. Мы выбираем шрифт Helvetica и определяем, что содержимое будет отображаться как inline-block с выравниванием по центру.

ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";

Следующий код устанавливает цвет, шрифт и отступы для тегов body, H1 и p.

ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";

Установка заголовка веб-страницы

Далее устанавливается заголовок веб-страницы. Вы можете изменить этот текст на любой, подходящий для вашего приложения.

ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP32 Weather Report</h1>\n";

Отображение температуры и влажности на веб-странице

Мы использовали тег параграфа для отображения значений температуры и влажности. Обратите внимание, что эти значения преобразуются в целые числа с помощью приведения типов.

  ptr +="<p>Temperature: ";
  ptr +=(int)Temperaturestat;
  ptr +="°C</p>";
  ptr +="<p>Humidity: ";
  ptr +=(int)Humiditystat;
  ptr +="%</p>";

  ptr +="</div>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

Стилизация веб-страницы для более профессионального вида

Программисты имеют тенденцию упускать из виду эстетику, но приложив немного усилий, наша веб-страница может выглядеть более привлекательно. Скриншот ниже даст вам представление о том, что мы собираемся сделать.

Отображение температуры и влажности DHT11 DHT22 AM2302 на веб-сервере ESP32 — профессиональный вид

Разве это не потрясающе? Давайте теперь добавим стиль к нашей предыдущей HTML-странице. Для начала замените функцию SendHTML() в приведённом выше скетче на код ниже. Попробуйте загрузить новый скетч, а затем мы подробно его разберём.

String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
  ptr +="<title>ESP32 Weather Report</title>\n";
  ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
  ptr +="body{margin-top: 50px;}\n";
  ptr +="h1 {margin: 50px auto 30px;}\n";
  ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
  ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
  ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
  ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
  ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n";
  ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
  ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n";
  ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
  ptr +=".data{padding: 10px;}\n";
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";

   ptr +="<div id=\"webpage\">\n";

   ptr +="<h1>ESP32 Weather Report</h1>\n";
   ptr +="<div class=\"data\">\n";
   ptr +="<div class=\"side-by-side temperature-icon\">\n";
   ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n";
   ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n";
   ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n";
   ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n";
   ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n";
   ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n";
   ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n";
   ptr +="</svg>\n";
   ptr +="</div>\n";
   ptr +="<div class=\"side-by-side temperature-text\">Temperature</div>\n";
   ptr +="<div class=\"side-by-side temperature\">";
   ptr +=(int)TempCstat;
   ptr +="<span class=\"superscript\">°C</span></div>\n";
   ptr +="</div>\n";
   ptr +="<div class=\"data\">\n";
   ptr +="<div class=\"side-by-side humidity-icon\">\n";
   ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
   ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
   ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
   ptr +="</svg>\n";
   ptr +="</div>\n";
   ptr +="<div class=\"side-by-side humidity-text\">Humidity</div>\n";
   ptr +="<div class=\"side-by-side humidity\">";
   ptr +=(int)Humiditystat;
   ptr +="<span class=\"superscript\">%</span></div>\n";
   ptr +="</div>\n";

  ptr +="</div>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

Объяснение кода

Мы уже знаем, что объявление <!DOCTYPE> информирует браузер о том, что мы отправляем HTML-код, а мета-элемент <meta> viewport делает веб-страницу адаптивной. Единственное отличие здесь в том, что мы будем использовать Google Fonts. Google предлагает сотни бесплатных веб-шрифтов для коммерческого и личного использования.

Для нашего веб-сайта мы будем использовать веб-шрифт Open Sans, заказанный Google. Google-шрифт встраивается в раздел head вашего HTML-документа с помощью тега <link>.

Для нашей страницы мы выбрали начертания шрифта 300 (Light), 400 (Regular) и 600 (Bold). Вы можете выбрать столько, сколько хотите, но имейте в виду, что слишком много начертаний замедляют загрузку страницы.

Вы также можете добавить курсивный стиль, просто добавив символ i в конце значения начертания, например, 400i встроит шрифт обычного курсивного начертания.

Важно отметить, что шрифты Google загружаются динамически; вы не сможете увидеть Google-шрифт, если у устройства, с которого вы заходите на эту страницу, нет активного подключения к интернету.

String SendHTML(float TempCstat,float TempFstat,float Humiditystat){
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";

Далее мы применим шрифт Open Sans ко всему HTML-документу. Мы также должны указать sans-serif в качестве запасного шрифта. Если первый указанный шрифт не загрузится, браузер попытается загрузить запасной шрифт.

ptr +="<title>ESP32 Weather Report</title>\n";
ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
ptr +="body{margin-top: 50px;}\n";
ptr +="h1 {margin: 50px auto 30px;}\n";

Далее мы применяем CSS для влажности и температуры — иконки, заголовки и значения. Все три этих элемента расположены в строку и выровнены по вертикали. Фон иконки сделан круглым с помощью border-radius 50% и высоты и ширины 30px.

ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n";
ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n";
ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
ptr +=".data{padding: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";

Далее мы отображаем показания температуры с этой аккуратной маленькой иконкой.

Иконка температуры — это изображение в формате Scalable Vector Graphics (SVG), определённое в теге <svg>. Создание SVG не требует специальных навыков программирования. Вы можете создавать графику для своей страницы с помощью Google SVG Editor. После иконки мы отображаем фактические показания температуры с датчика.

ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP32 Weather Report</h1>\n";
ptr +="<div class=\"data\">\n";

ptr +="<div class=\"side-by-side temperature-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n";
ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n";
ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n";
ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n";
ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n";
ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n";
ptr +="</svg>\n";
ptr +="</div>\n";

ptr +="<div class=\"side-by-side temperature-text\">Temperature</div>\n";
ptr +="<div class=\"side-by-side temperature\">";
ptr +=(int)TempCstat;
ptr +="<span class=\"superscript\">°C</span></div>\n";
ptr +="</div>\n";

С помощью этой иконки мы отображаем показания влажности.

Это ещё один SVG. После вывода значений влажности мы закрываем все открытые теги, такие как body и html.

ptr +="<div class=\"data\">\n";
ptr +="<div class=\"side-by-side humidity-icon\">\n";
ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
ptr +="</svg>\n";
ptr +="</div>\n";
ptr +="<div class=\"side-by-side humidity-text\">Humidity</div>\n";
ptr +="<div class=\"side-by-side humidity\">";
ptr +=(int)Humiditystat;
ptr +="<span class=\"superscript\">%</span></div>\n";
ptr +="</div>\n";

ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}

Улучшение 1 — Автоматическое обновление страницы

Одно из улучшений, которое вы можете сделать, — это автоматическое обновление страницы для обновления значений датчика.

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

<meta http-equiv="refresh" content="2" >

Вставьте этот код в тег <head> вашего документа; этот мета-тег укажет браузеру обновлять страницу каждые две секунды.

Улучшение 2 — Динамическая загрузка данных датчика с помощью AJAX

Обновление веб-страницы непрактично, если веб-страница большая. Асинхронный Javascript и Xml (AJAX) — это лучший метод, поскольку он позволяет нам запрашивать данные с сервера асинхронно (в фоновом режиме) без обновления страницы.

Объект XMLHttpRequest в JavaScript обычно используется для выполнения AJAX на веб-страницах. Он отправляет скрытый GET-запрос к серверу и обновляет элемент страницы. AJAX — это не новая технология и не другой язык программирования; это просто существующая технология, используемая по-другому. Она позволяет:

  • Запрашивать данные с сервера после загрузки страницы

  • Получать данные с сервера после загрузки страницы

  • Отправлять данные на сервер в фоновом режиме

Вот AJAX-скрипт, который мы будем использовать. Разместите этот скрипт перед закрывающим тегом <head>.

ptr +="<script>\n";
ptr +="setInterval(loadDoc,200);\n";
ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";
ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
ptr +="};\n";
ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";
ptr +="</script>\n";

Объяснение кода

Поскольку AJAX-скрипт — это просто javascript, он должен быть заключён в тег <script>. Мы будем использовать javascript-функцию setInterval() для многократного вызова этой функции. Она требует два параметра: функцию для выполнения и временной интервал (в миллисекундах).

ptr +="<script>\n";
ptr +="setInterval(loadDoc,200);\n";

Функция loadDoc() — самая важная часть этого скрипта. В ней создаётся объект XMLHttpRequest(). Этот объект используется для запроса данных у веб-сервера.

ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";

Метод xhttp.onreadystatechange() вызывается каждый раз при изменении readyState. Свойство readyState представляет состояние XMLHttpRequest. Оно может принимать одно из следующих значений:

  • 0: запрос не инициализирован

  • 1: соединение с сервером установлено

  • 2: запрос получен

  • 3: обработка запроса

  • 4: запрос завершён и ответ готов

Свойство status содержит статус объекта XMLHttpRequest. Оно может принимать одно из следующих значений:

  • 200: «OK»

  • 403: «Forbidden»

  • 404: «Page not found»

Когда readyState равен 4 и status равен 200, ответ завершён, и содержимое элемента с id „webpage“ (div, содержащий значения температуры и влажности) обновляется.

ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
ptr +="};\n";

Затем функции open() и send() используются для инициации HTTP-запроса.

ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";