Общие сведения:
В этом проекте мы настроим 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.
// Подключаем библиотеки #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); }
Скетч с добавлением в файл и записью показаний с текущим реальным временем
// Подключаем библиотеки #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); }
Обсуждение