Веб-сервер ESP8266, использующий SPIFFS (файловая система SPI Flash) – NodeMCU

В этом руководстве показано, как создать веб-сервер, который обслуживает файлы HTML и CSS, хранящиеся в файловой системе ESP8266 NodeMCU (SPIFFS), используя Arduino IDE. Вместо того, чтобы записывать текст HTML и CSS в Arduino sketch, мы создадим отдельные файлы HTML и CSS.

Веб-сервер, который мы создадим, показывает, как управлять выходами ESP8266 и как отображать показания датчиков. В качестве примера мы будем управлять светодиодом и отображать показания датчиков с датчика BME280.

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

Обзор проекта

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

  • Веб-сервер управляет светодиодом, подключенным к ESP8266 GPIO 2. Это встроенный светодиод ESP8266. Вы можете управлять любым другим GPIO;
  • На странице веб-сервера показаны две кнопки: ВКЛ. и ВЫКЛ. – для включения и выключения GPIO 2;
  • На странице веб-сервера также показано текущее состояние GPIO;
  • Вы также будете использовать датчик BME280 для отображения показаний датчиков (температуры, влажности и давления).

На следующем рисунке показана упрощенная схема, демонстрирующая, как все работает.

Предварительные требования

Прежде чем приступить к этому проекту, убедитесь, что вы проверили все следующие предварительные требования.

1. Установите плату ESP8266 в Arduino IDE

Мы будем программировать ESP8266 с помощью Arduino IDE, поэтому у вас должно быть установлено дополнение ESP8266. Следуйте следующему руководству, чтобы установить его:

2. Плагин для загрузки файловой системы

Для загрузки файлов в файловую систему ESP8266 SPI Flash (SPIFFS) мы будем использовать плагин Filesystem Uploader. Установите плагин в вашу Arduino IDE:

3. Установка библиотек

Один из самых простых способов создания веб-сервера с использованием файлов из файловой системы – это использование библиотеки ESPAsyncWebServer .

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

Эта библиотека недоступна для загрузки через Arduino IDE libraries manager. Итак, вам необходимо выполнить следующие шаги для установки библиотеки:

  1. Нажмите здесь, чтобы загрузить библиотеку ESPAsyncWebServer. У вас должна быть папка .zip в папке загрузок
  2. Распакуйте ZIP-папку, и вы должны получить ESPAsyncWebServer-главную папку
  3. Переименуйте вашу папку из ESPAsyncWebServer-master в ESPAsyncWebServer
  4. Переместите папку ESPAsyncWebServer в папку установочных библиотек Arduino IDE

В качестве альтернативы вы можете перейти в Sketch > Include Library > .zip Library и выбрать ранее загруженную библиотеку.

Установка ESPAsyncTCP

Для правильной работы библиотеки ESPAsyncWebServer также требуется библиотека ESPAsyncTCP. Следуйте следующим шагам, чтобы установить библиотеку ESPAsyncTCP.:

  1. Нажмите здесь, чтобы загрузить библиотеку ESPAsyncTCP. У вас должна быть папка .zip в папке загрузок
  2. Распакуйте zip-папку, и вы должны получить ESPAsyncTCP-главную папку
  3. Переименуйте вашу папку из ESPAsyncTCP-master в ESPAsyncTCP
  4. Переместите папку ESPAsyncTCP в папку установочных библиотек Arduino IDE
  5. Наконец, повторно откройте Arduino IDE

В качестве альтернативы вы можете перейти в Sketch > Include Library > .zip Library и выбрать ранее загруженную библиотеку.

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

В этом руководстве мы отобразим показания датчика BME280 (Руководство по ESP8266). Вам необходимо установить следующие библиотеки:

Вы можете установить эти библиотеки через Arduino IDE Libraries Manager. Перейдите в Sketch Включить библиотеки > Управление библиотеками. Затем выполните поиск по названию библиотек, чтобы установить их.

Требуются запчасти

Чтобы продолжить работу над этим проектом, вам понадобятся следующие части:

Принципиальная схема

Подключите все компоненты, следуя следующей принципиальной схеме.

BME280ESP8266
Vin3.3В
GNDGND
SCLGPIO 5
SDAGPIO 4

Организация ваших файлов

Для сборки веб-сервера вам понадобятся три разных файла. Эскиз Arduino, HTML-файл и CSS-файл. Файлы HTML и CSS следует сохранить в папке с именем data внутри папки Arduino sketch, как показано ниже:

Создание HTML-файла

Создайте index.html файл со следующим содержимым или загрузите все файлы проекта здесь:

<!DOCTYPE html>
<!-- 
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com  
-->
<html>
<head>
  <title>ESP8266 Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <h1>ESP8266 Web Server</h1>
  <p>GPIO state<strong> %STATE%</strong></p>
  <p>
    <a href="/on"><button class="button">ON</button></a>
    <a href="/off"><button class="button button2">OFF</button></a>
  </p>
  <p>
    <span class="sensor-labels">Temperature</span>
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <span class="sensor-labels">Humidity</span>
    <span id="humidity">%HUMIDITY%</span>
    <sup class="units">&#37;</sup>
  </p>
  <p>
    <span class="sensor-labels">Pressure</span>
    <span id="pressure">%PRESSURE%</span>
    <sup class="units">hPa</sup>
  </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("pressure").innerHTML = this.responseText;
      }
    };
    xhttp.open("GET", "/pressure", true);
    xhttp.send();
  }, 10000 ) ;
</script>
</html>

Просмотреть необработанный код

Поскольку мы используем CSS и HTML в разных файлах, нам нужно ссылаться на файл CSS в тексте HTML.

<link rel="stylesheet" type="text/css" href="style.css">

Тег <link> сообщает HTML-файлу, что вы используете внешнюю таблицу стилей для форматирования внешнего вида страницы. Атрибут rel определяет природу внешнего файла, в данном случае это таблица стилей — файл CSS, — который будет использоваться для изменения внешнего вида страницы.

Для атрибута type установлено значение “text / css”, чтобы указать, что вы используете CSS-файл для стилей. Атрибут href указывает местоположение файла; поскольку файлы CSS и HTML будут находиться в одной папке, вам просто нужно указать имя файла: style.css.

В следующей строке мы пишем первый заголовок нашей веб-страницы. В данном случае у нас есть “Веб-сервер ESP8266”. Вы можете изменить заголовок на любой текст:

<h1>ESP8266 Web Server</h1>

Затем добавьте абзац с текстом “Состояние GPIO: ”, за которым следует состояние GPIO. Поскольку состояние GPIO изменяется соответственно состоянию GPIO, мы можем добавить заполнитель, который затем будет заменен на любое значение, которое мы установили в эскизе Arduino.

Для добавления заполнителя используйте знаки %. Чтобы создать заполнитель для состояния, вы можете использовать, например, %STATE%.

<p>GPIO state<strong> %STATE%</strong></p>

Вы присваиваете значение заполнителю состояния в эскизе Arduino.

Затем создайте кнопки включения и выключения. Когда вы нажимаете кнопку включения, мы перенаправляем веб-страницу в to root, за которым следует /on URL. При нажатии кнопки off вы перенаправляетесь на / off URL.

<a href="/on"><button class="button">ON</button></a>
<a href="/off"><button class="button button2">OFF</button></a>

Наконец, создайте три абзаца для отображения температуры, влажности и давления.

<p>
  <span class="sensor-labels">Temperature</span>
  <span id="temperature">%TEMPERATURE%</span>
  <sup class="units">°C</sup>
</p>
<p>
  <span class="sensor-labels">Pressure</span>
  <span id="pressure">%PRESSURE%</span>
  <sup class="units">hPa</sup>
</p>
<p>
  <span class="sensor-labels">Humidity</span>
  <span id="humidity">%HUMIDITY%</span>
  <sup class="units">%</sup>
</p>

Мы используем заполнители % TEMPERATURE%, %MOISTURE% и %PRESSURE%. Затем они будут заменены фактическими показаниями температуры в эскизе Arduino.

Автоматические обновления

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

Следующий фрагмент кода отвечает за температуру.

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 (), которая запускается каждые 10 секунд.

По сути, он отправляет запрос в / temperature URL, чтобы получить последние показания температуры.

  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

Когда он получает это значение, он обновляет HTML-элемент идентификатором температуры.

if (this.readyState == 4 && this.status == 200) {
  document.getElementById("temperature").innerHTML = this.responseText;
}

Вкратце, этот предыдущий раздел отвечает за асинхронное обновление температуры. Тот же процесс повторяется для показаний влажности и давления.

Создание файла CSS

Создайте файл style.css со следующим содержимым или загрузите все файлы проекта здесь:

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

html {
  font-family: Arial;
  display: inline-block;
  margin: 0px auto;
  text-align: center;
}
h1 {
  color: #0F3376;
  padding: 2vh;
}
p {
  font-size: 1.5rem;
}
.button {
  display: inline-block;
  background-color: #008CBA;
  border: none;
  border-radius: 4px;
  color: white;
  padding: 16px 40px;
  text-decoration: none;
  font-size: 30px;
  margin: 2px;
  cursor: pointer;
}
.button2 {
  background-color: #f44336;
}
.units {
  font-size: 1.2rem;
 }
.sensor-labels {
  font-size: 1.5rem;
  vertical-align:middle;
  padding-bottom: 15px;
}

Просмотреть необработанный код

Это всего лишь базовый CSS-файл для настройки размера шрифта, стиля и цвета кнопок и выравнивания страницы. Мы не будем объяснять, как работает CSS. Хорошим местом для изучения CSS является веб-сайт W3Schools.

Скетч асинхронного веб-сервера ESP8266

Скопируйте следующий код в Arduino IDE или загрузите все файлы проекта здесь. Затем вам нужно ввести свои сетевые учетные данные (SSID и пароль), чтобы подключить ESP8266 к вашей локальной сети.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

// Import required libraries
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

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

// Set LED GPIO
const int ledPin = 2;
// Stores LED state
String ledState;

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

String getTemperature() {
  float temperature = bme.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  //float temperature = 1.8 * bme.readTemperature() + 32;
  Serial.println(temperature);
  return String(temperature);
}
  
String getHumidity() {
  float humidity = bme.readHumidity();
  Serial.println(humidity);
  return String(humidity);
}

String getPressure() {
  float pressure = bme.readPressure()/ 100.0F;
  Serial.println(pressure);
  return String(pressure);
}

// Replaces placeholder with LED state value
String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if(digitalRead(ledPin)){
      ledState = "ON";
    }
    else{
      ledState = "OFF";
    }
    Serial.print(ledState);
    return ledState;
  }
  else if (var == "TEMPERATURE"){
    return getTemperature();
  }
  else if (var == "HUMIDITY"){
    return getHumidity();
  }
  else if (var == "PRESSURE"){
    return getPressure();
  }
  return String();
}
 
void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);

  // Initialize the sensor
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // Initialize SPIFFS
  if(!SPIFFS.begin()){
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP32 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
  
  // Route to load style.css file
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/style.css", "text/css");
  });

  // Route to set GPIO to HIGH
  server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, HIGH);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
  
  // Route to set GPIO to LOW
  server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, LOW);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", getTemperature().c_str());
  });
  
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", getHumidity().c_str());
  });
  
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", getPressure().c_str());
  });

  // Start server
  server.begin();
}
 
void loop(){
  
}

Просмотреть необработанный код

Как работает код

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

Во-первых, включите необходимые библиотеки:

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

Вам необходимо ввести свои сетевые учетные данные в следующих переменных:

const char* ssid = "REPLACE_WITH_YOUR_SSID"; 
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Создайте экземпляр, который ссылается на датчик BME280 под названием bme:

Adafruit_BME280 bme; // I2C

Затем создайте переменную, которая ссылается на GPIO 2, называемую ledPin, и строковую переменную для хранения состояния светодиода: ledState.

const int ledPin = 2;
String ledState;

Создайте объект AsynWebServer с именем server, который прослушивает порт 80.

AsyncWebServer server(80);

Получение показаний датчиков

Мы создаем три функции для возврата показаний датчика в виде строк: функции getTemperature(), getHumidity() и getPressure().

Вот как выглядит функция getTemperature() (другие функции аналогичны).

String getTemperature() {
  float temperature = bme.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  //float temperature = 1.8 * bme.readTemperature() + 32;
  Serial.println(temperature);
  return String(temperature);
}

Если вы хотите отображать температуру в градусах Фаренгейта, вам просто нужно раскомментировать соответствующую строку в функции getTemperature():

float temperature = 1.8 * bme.readTemperature() + 32;

Чтобы узнать больше о взаимодействии датчика BME280 с ESP8266, вы можете прочитать следующее руководство:

processor()

Функция processor() присваивает значение заполнителям, которые мы создали в HTML-файле. Он принимает в качестве аргумента заполнитель и должен возвращать строку, которая заменит заполнитель. Функция processor() должна иметь следующую структуру:

String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if(digitalRead(ledPin)){
      ledState = "ON";
    }
    else{
      ledState = "OFF";
    }
    Serial.print(ledState);
    return ledState;
  }
  else if (var == "TEMPERATURE"){
    return getTemperature();
  }
  else if (var == "HUMIDITY"){
    return getHumidity();
  }
  else if (var == "PRESSURE"){
    return getPressure();
  }
}

Эта функция сначала проверяет, соответствует ли заполнитель СОСТОЯНИЮ, которое мы создали в HTML-файле.

if(var == "STATE"){

Если это так, то, в зависимости от состояния светодиода, мы устанавливаем переменную ledState либо включенной, либо ВЫКЛЮЧЕННОЙ.

if(digitalRead(ledPin)){
  ledState = "ON";
}
else{
  ledState = "OFF";
}

Наконец, мы возвращаем переменную ledState. Это заменяет заполнитель STATE строковым значением ledState.

return ledState;

Если он находит заполнитель %TEMPERATURE%, мы возвращаем температуру, вызывая getTemperature() функция, созданная ранее.

else if (var == "TEMPERATURE"){
  return getTemperature();
}

То же самое происходит с заполнителями %ВЛАЖНОСТИ% и %ДАВЛЕНИЯ%, вызывая соответствующие функции:

else if (var == "TEMPERATURE"){
  return getTemperature();
}
else if (var == "HUMIDITY"){
  return getHumidity();
}
else if (var == "PRESSURE"){
  return getPressure();
}  

настройка ()

В setup () начните с инициализации последовательного монитора и настройки GPIO в качестве выходного сигнала.

Serial.begin(115200);
pinMode(ledPin, OUTPUT);

Инициализируем датчик BME280:

if (!bme.begin(0x76)) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
}

Инициализация SPIFFS:

if(!SPIFFS.begin()){
  Serial.println("An Error has occurred while mounting SPIFFS");
  return;
}

Подключение по Wi-Fi

Подключитесь к Wi-Fi и выведите адрес ESP8266:

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());

Асинхронный веб-сервер

Библиотека ESPAsyncWebServer позволяет нам настраивать маршруты, по которым сервер будет прослушивать входящие HTTP-запросы, и выполнять функции при получении запроса по этому маршруту. Для этого используйте метод on на объекте server следующим образом:

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(SPIFFS, "/index.html", String(), false, processor);
});

Когда сервер получает запрос по корневому URL “/”, он отправляет index.htmlфайл клиенту. Последним аргументом функции send() является процессор, так что мы можем заменить заполнитель на нужное нам значение – в данном случае на ledState .

Поскольку мы ссылаемся на файл CSS в файле HTML, клиент сделает запрос на файл CSS. Когда это произойдет, файл CSS отправляется клиенту:

server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(SPIFFS, "/style.css","text/css");
});

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

server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
  digitalWrite(ledPin, HIGH);
  request->send(SPIFFS, "/index.html", String(),false, processor);
});
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
  digitalWrite(ledPin, LOW);
  request->send(SPIFFS, "/index.html", String(),false, processor);
});

В HTML-файле мы написали код JavaScript, который запрашивает температуру, влажность и давление по маршрутам / temperature, / humidity, / pressure соответственно каждые 10 секунд. Итак, нам также нужно обработать то, что происходит, когда мы получаем запрос по этим маршрутам.

Нам просто нужно отправить обновленные показания датчика. Обновленные показания датчика возвращаются с помощью функций getTemperature(), getHumidity() и getPressure(), которые мы создали ранее.

Показания представляют собой обычный текст и должны быть отправлены в виде символа, поэтому мы используем метод c_str().

server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", getTemperature().c_str());
});
  
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", getHumidity().c_str());
});
  
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", getPressure().c_str());
});

В конце мы используем метод begin() на объекте server, чтобы сервер начал прослушивать входящих клиентов.

server.begin();

Поскольку это асинхронный веб-сервер, вы можете определять все запросы в setup(). Затем вы можете добавить другой код в цикл (), пока сервер прослушивает входящих клиентов.

Загрузка кода и файлов

Сохраните эскиз Arduino как ESP8266_SPIFFS_Web_Server или загрузите все файлы проекта здесь.

  • Перейдите в Sketch > Показать папку Sketch и создайте папку с именем data. Сохраните файлы HTML и CSS внутри этой папки;
  • В разделе Инструменты Плата выберите используемую плату ESP8266;
  • Затем перейдите в Инструменты Размер флэш-памяти и выберите 4 М (SPIFFS 1 М).
Выберите плату ESP8266 NodeMCU с SPIFFS Arduino IDE

Наконец, загрузите файлы на свою плату. Перейдите в Инструменты > Загрузка эскиза данных ESP8266 и дождитесь загрузки файлов.

Загрузка файлов в ESP8266 NodeMCU SPIFFS Загрузка данных эскиза ESP8266

Затем нажмите кнопку загрузки Arduino IDE, чтобы загрузить код на ESP8266.

Загрузите код Arduino IDE в ESP8266 NodeMCU

Когда все будет успешно загружено, откройте последовательный монитор со скоростью передачи 115200 бод. Нажмите первую кнопку ESP8266 на плате, и он должен напечатать IP-адрес ESP8266.

Последовательный мониторинг IP-адреса ESP8266 NodeMCU Arduino IDE

Демонстрация

Откройте браузер и введите свой IP-адрес ESP8266. Должна загрузиться следующая веб-страница.

Веб-сервер ESP8266, использующий SPIFFS, демонстрация HTML CSS страницы

Нажимайте кнопки включения и выключения для управления встроенным светодиодом ESP8266. Вы также можете визуализировать последние показания датчика. Показания датчика обновляются автоматически без необходимости обновлять веб-страницу.

Подведение итогов

Использование флэш-файловой системы ESP8266 SPI (SPIFFS) особенно полезно для хранения файлов HTML и CSS для обслуживания клиента – вместо того, чтобы писать весь код в Arduino sketch.

Вот еще похожая статья

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии