Главная chevron_right Наши уроки chevron_right ESP32 chevron_right Создаём и скачиваем файлы из внутренней памяти Piranha ESP32

Создаём и скачиваем файлы из внутренней памяти Piranha ESP32

Подключаем Piranha ESP32 к WiFi, создаём файлы во встроенной памяти SPIFFS и скачиваем их через локальный Web-сервер прямо в браузере — удобный способ вести журнал показаний дат...

Общие сведения:

В этом проекте мы настроим Piranha ESP32 на подключение к существующей точке доступа WiFi, запустим Web-сервер ESP32, создадим файл во встроенной памяти при помощи файловой системы SPIFFS, а при подключении к локальному Web-сайту по имени piranha-logger.local можно будет скачать файл, в который с периодичностью в десять секунд записываются текущие millis().

Для работы данного скетча внутренняя память Piranha ESP32 должна быть отформатирована. Для этого либо воспользуйтесь утилитой загрузки файлов на Piranha ESP32, либо раскомментируйте строку SPIFFS.format() в функции setup().

  • Процедуру форматирования необходимо выполнить только один раз.
  • При использовании любого метода все файлы, загруженные вами или созданные скетчем ранее, будут удалены.
  • Если процедуру форматирования не убрать из скетча и не загрузить новую версию скетча в плату, то память будет очищаться при каждом включении или перезагрузке микроконтроллера.
  • Процедура format() занимает относительно долгое время, будьте терпеливы.

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

В этом примере файл перезаписывается каждый раз. Для записи с сохранением предыдущих показаний измените способ открытия файла с "w" на "a"SPIFFS.open("/logger.txt", "w") на SPIFFS.open("/logger.txt", "a")).

Данный подход, например, можно использовать для ведения журнала показаний датчиков за небольшой промежуток времени. Стоит помнить, что памяти, доступной для файловой системы, 1 МБ. Если нужно вести длительные наблюдения показаний, стоит воспользоваться записью файлов на внешний носитель (например на SD-карту).

Скачивание файлов

В данном примере создаётся локальный Web-сайт, доступ к которому можно получить по ссылке http://piranha-logger.local. Сайт генерируется кодом скетча и выводит список файлов, хранящихся во внутренней памяти, на указанный выше локальный сайт. Доступ по имени возможен благодаря серверу mDNS (Multicast DNS), библиотеку которого мы используем в скетче. Если по каким-то причинам mDNS не работает в локальной сети - то сайт может быть доступен по адресу, который выводится в последовательный порт сразу после подключения к точке WiFi.

Видео:

редактируется ...

Нам понадобится:

Подключение:

Скетчи проекта:

Скетч с перезаписью файла. В скетче необходимо указать Ваши данные для Вашей точки доступа WiFi.

Копировать123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183`// Подключаем библиотеки #include <WiFi.h> #include <WebServer.h> #include <ESPmDNS.h> #include <SPIFFS.h>

// Определяем интервал записи в файл const unsigned long INTERVAL = 10000; unsigned long write_millis = 0;

// Определяем название и пароль точки доступа const char ssid = "название_WiFi"; // Это поле нужно заполнить необходимыми данными const char password = "пароль_WiFi"; // Это поле нужно заполнить необходимыми данными

// Определяем имя сервера в сети const char* host = "piranha-logger";

// Создаём объект Веб-сервера WebServer server(80);

// Функция обработки клиента void handleClient() { // Выводим содержимое корневого каталога как Веб-страницу listRootToHtml(); }

// Функция чтения файла bool handleFileRead(String path) { // Открываем файл для чтения по указанному пути File file = SPIFFS.open(path, "r");

// Если файл не удалось открыть if (!file) { Serial.println("Ошибка. Файл не существует.");

// Отвечаем клиенту ошибкой server.send(404, "text/plain", "FileNotFound");

// Возвращаемся из функции return false; }

// Отдаём клиенту содержимое файла server.streamFile(file, "text/html"); // Закрываем файл file.close(); // Возвращаемся из функции return true; }

// Функция вывода списка файлов в HTML страницу void listRootToHtml() { // Открываем корневой файл File root = SPIFFS.open("/");

// Если не получилось открыть if (!root) { // Выводим ошибку Serial.println("error"); // Возвращаемся из функции return; }

// Создаём строку для конкатенации String html = "<html><meta charset=\"UTF-8\"><body>";

// Если корневой файл - каталог if (root.isDirectory()) {

// Открываем следующий файл File file = root.openNextFile();

// Входим в цикл, если файл существует / После прохода данного цикла должна получиться страница вида: <html><meta charset="UTF-8"><body> <p><a href="имя_первого_файла download="имя_первого_файла"> имя_первого_файла</a></p> <p><a href="имя_второго_файла download="имя_второго_файла"> имя_второго_файла</a></p> ..... <p><a href="имя_N-фала download="имя_N-файла"> имя_N-файла</a></p> </body></html> / while (file) {

// Записываем имя файла String name = file.name();

// Удаляем первый символ ("/"); name.remove(0, 1);

// Конкатенируем строку html += "<p><a href=\""; html += name; html += (String)"\" download=\""; html += name +"\">"; html += name; html += "</a></p>";

// Открываем следующий файл file = root.openNextFile(); } html += "</body></html>"; }

// Отравляем страницу клиенту server.send(200, "text/html", html); }

void setup() {

// Форматируем внутренную память (нужно выполнить только один раз) // SPIFFS.format();

// Инициируем объект файловой системы SPIFFS.begin();

Serial.begin(115200); Serial.println(); Serial.println("Подключаемся к WiFi");

// Инициируем точку доступа WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { Serial.print('.'); delay(100); } // Записываем IP-адрес IPAddress myIP = WiFi.localIP();

// Инициируем Multicast DNS MDNS.begin(host);

// Выводим IP-адрес Веб-сервера Serial.print("IP-адрес: "); Serial.println(myIP);

// Функция, выполняемая при подключении к клиента корневому каталогу server.on("/", HTTP_GET, handleClient); // Функция, которая будет выполнена, если файл не найден server.onNotFound([]() { // Если по указанному пути файл не найден... if (!handleFileRead(server.uri())) { // Отвечаем клиенту ошибкой 404 server.send(404, "text/plain", "FILE NOT FOUND"); } });

// Инициируем сервер server.begin(); Serial.println("Сервер запущен."); }

void loop() { // Библиотечная функция обработки клиента server.handleClient();

// Если прошёл интервал ожидания if (millis() - write_millis > INTERVAL) { // Записываем текущие millis write_millis = millis(); // Создаём файл с абсолютным путём File file = SPIFFS.open("/logger.txt", "w");

// Если файл не получилось создать if (!file) // Выводим сообщение Serial.println("error creating file"); // Иначе else // Выводим текущие millis в файл file.println(write_millis); file.flush(); file.close(); } // Даём процессору переключиться на другие задачи delay(2); }`

Скетч с добавлением в файл и записью показаний с текущим реальным временем

Копировать123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197`// Подключаем библиотеки #include <WiFi.h> #include <WebServer.h> #include <ESPmDNS.h> #include <SPIFFS.h> #include "time.h"

// Определяем интервал записи в файл const unsigned long INTERVAL = 10000; unsigned long write_millis = 0;

// Определяем название и пароль точки доступа const char ssid = "название_WiFi"; // Это поле нужно заполнить необходимыми данными const char password = "пароль_WiFi"; // Это поле нужно заполнить необходимыми данными

// Определяем сервер времени const char* ntpServer = "pool.ntp.org";

// Определяем имя сервера в сети const char* host = "piranha-logger";

// Создаём объект Веб-сервера WebServer server(80);

// Функция обработки клиента void handleClient() { // Выводим содержимое корневого каталога как Веб-страницу listRootToHtml(); }

// Функция чтения файла bool handleFileRead(String path) { // Открываем файл для чтения по указанному пути File file = SPIFFS.open(path, "r");

// Если файл не удалось открыть if (!file) { Serial.println("Ошибка. Файл не существует.");

// Отвечаем клиенту ошибкой server.send(404, "text/plain", "FileNotFound");

// Возвращаемся из функции return false; }

// Отдаём клиенту содержимое файла server.streamFile(file, "text/html"); // Закрываем файл file.close(); // Возвращаемся из функции return true; }

// Функция вывода списка файлов в HTML страницу void listRootToHtml() { // Открываем корневой файл File root = SPIFFS.open("/");

// Если не получилось открыть if (!root) { // Выводим ошибку Serial.println("error"); // Возвращаемся из функции return; }

// Создаём строку для конкатенации String html = "<html><meta charset=\"UTF-8\"><body>";

// Если корневой файл - каталог if (root.isDirectory()) {

// Открываем следующий файл File file = root.openNextFile();

// Входим в цикл, если файл существует / После прохода данного цикла должна получиться страница вида: <html><meta charset="UTF-8"><body> <p><a href="имя_первого_файла download="имя_первого_файла"> имя_первого_файла</a></p> <p><a href="имя_второго_файла download="имя_второго_файла"> имя_второго_файла</a></p> ..... <p><a href="имя_N-фала download="имя_N-файла"> имя_N-файла</a></p> </body></html> / while (file) {

// Записываем имя файла String name = file.name();

// Удаляем первый символ ("/"); name.remove(0, 1);

// Конкатенируем строку html += "<p><a href=\""; html += name; html += (String)"\" download=\""; html += name +"\">"; html += name; html += "</a></p>";

// Открываем следующий файл file = root.openNextFile(); } html += "</body></html>"; }

// Отравляем страницу клиенту server.send(200, "text/html", html); }

void setup() {

// Форматируем внутренную память (нужно выполнить только один раз) // SPIFFS.format();

// Инициируем объект файловой системы SPIFFS.begin();

Serial.begin(115200); Serial.println(); Serial.println("Подключаемся к WiFi");

// Инициируем точку доступа WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { Serial.print('.'); delay(100); } // Записываем IP-адрес IPAddress myIP = WiFi.localIP();

// Инициируем Multicast DNS MDNS.begin(host);

// Выводим IP-адрес Веб-сервера Serial.print("IP-адрес: "); Serial.println(myIP);

// Конфигурируем время configTime(3600*3, 0, ntpServer);

// Функция, выполняемая при подключении к клиента корневому каталогу server.on("/", HTTP_GET, handleClient); // Функция, которая будет выполнена, если файл не найден server.onNotFound([]() { // Если по указанному пути файл не найден... if (!handleFileRead(server.uri())) { // Отвечаем клиенту ошибкой 404 server.send(404, "text/plain", "FILE NOT FOUND"); } });

// Инициируем сервер server.begin(); Serial.println("Сервер запущен."); }

void loop() { // Библиотечная функция обработки клиента server.handleClient();

// Если прошёл интервал ожидания if (millis() - write_millis > INTERVAL) { // Записываем текушее время struct tm timeinfo; getLocalTime(&timeinfo);

// Записываем текущие millis write_millis = millis(); // Создаём файл с абсолютным путём File file = SPIFFS.open("/logger.txt", "a");

// Если файл не получилось создать if (!file) // Выводим сообщение Serial.println("error creating file"); // Иначе else // Выводим текущее время в файл file.print(&timeinfo, "%B %d %Y %H:%M:%S,");

// Выводим текущие millis в файл file.println(write_millis); file.flush(); file.close(); } // Даём процессору переключиться на другие задачи delay(2); }`

Ссылки

Комплект для повторения проекта

Что понадобится

Это быстрый ориентир по основным модулям и деталям. Полный список для повторения проекта смотрите в самой статье.

2 позиции
Все уроки ESP32