Общие сведения:
В этом проекте мы настроим 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);
}
Ссылки
Комплект для повторения проекта
Что понадобится
Это быстрый ориентир по основным модулям и деталям. Полный список для повторения проекта смотрите в самой статье.
2 позиции