Настало время поместить в ESP8266 web страницы. Здесь нам поможет библиотека для работы с файловой системой FS.h
Библиотека входит в состав пакета и устанавливать ее не нужно.
Arduino ESP8266 filesystem uploader: https://github.com/esp8266/arduino-esp8266fs-plugin
Скетч с папкой web сервера: WiFiManager-IR-FS
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino //needed for library #include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h> //https://github.com/tzapu/WiFiManager #include <ESP8266SSDP.h> #include <aREST.h> #include <IRremoteESP8266.h> #include <FS.h> // Web интерфейс для устройства ESP8266WebServer HTTP(80); // aREST и сервер для него WiFiServer SERVERaREST(8080); aREST rest = aREST(); // Подключаем Ик передатчик к ноге IRsend irsend(14); File fsUploadFile; void setup() { // Настраиваем вывод отладки Serial.begin(115200); //Включаем WiFiManager WiFiManager wifiManager; //Если не удалось подключиться клиентом запускаем режим AP // доступ к настройкам по адресу http://192.168.4.1 wifiManager.autoConnect("AutoConnectAP"); //если подключение к точке доступа произошло сообщаем Serial.println("connected...yeey :)"); //настраиваем HTTP интерфейс HTTP_init(); //запускаем SSDP сервис Serial.printf("Starting SSDP...\n"); SSDP_init(); Serial.printf("SSDP Ready!\n"); // регистрируем в aRest функции irControl rest.function("irc", irControl); // включаем aREST и сервер к нему AREST_init(); Serial.println("aREST Server started"); // Включаем ИК передатчик irsend.begin(); } void loop() { // put your main code here, to run repeatedly: HTTP.handleClient(); delay(1); // Handle REST calls WiFiClient client = SERVERaREST.available(); if (!client) { return; } while (!client.available()) { delay(1); } rest.handle(client); } void SSDP_init(void) { SSDP.setSchemaURL("description.xml"); SSDP.setHTTPPort(80); SSDP.setName("FSWebServer"); SSDP.setSerialNumber("001788102201"); SSDP.setURL("/"); SSDP.setModelName("FSWebServer"); SSDP.setModelNumber("000000000001"); SSDP.setModelURL("http://esp8266-arduinoide.ru/fswebserver/"); SSDP.setManufacturer("Tretyakov Sergey"); SSDP.setManufacturerURL("http://www.esp8266-arduinoide.ru"); SSDP.begin(); } void HTTP_init(void) { // SSDP дескриптор HTTP.on("/description.xml", HTTP_GET, []() { SSDP.schema(HTTP.client()); }); // Инициализация FFS SPIFFS.begin(); { Dir dir = SPIFFS.openDir("/"); while (dir.next()) { String fileName = dir.fileName(); size_t fileSize = dir.fileSize(); } } //HTTP страницы для работы с FFS //list directory HTTP.on("/list", HTTP_GET, handleFileList); //загрузка редактора editor HTTP.on("/edit", HTTP_GET, []() { if (!handleFileRead("/edit.htm")) HTTP.send(404, "text/plain", "FileNotFound"); }); //Создание файла HTTP.on("/edit", HTTP_PUT, handleFileCreate); //Удаление файла HTTP.on("/edit", HTTP_DELETE, handleFileDelete); //first callback is called after the request has ended with all parsed arguments //second callback handles file uploads at that location HTTP.on("/edit", HTTP_POST, []() { HTTP.send(200, "text/plain", ""); }, handleFileUpload); //called when the url is not defined here //use it to load content from SPIFFS HTTP.onNotFound([]() { if (!handleFileRead(HTTP.uri())) HTTP.send(404, "text/plain", "FileNotFound"); }); //Обновление с web страницы HTTP.on("/update", HTTP_POST, []() { HTTP.sendHeader("Connection", "close"); HTTP.sendHeader("Access-Control-Allow-Origin", "*"); HTTP.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK"); ESP.restart(); }, []() { HTTPUpload& upload = HTTP.upload(); if (upload.status == UPLOAD_FILE_START) { Serial.setDebugOutput(true); WiFiUDP::stopAll(); Serial.printf("Update: %s\n", upload.filename.c_str()); uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; if (!Update.begin(maxSketchSpace)) { //start with max available size Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_WRITE) { if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { //true to set the size to the current progress Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); } else { Update.printError(Serial); } Serial.setDebugOutput(false); } yield(); }); HTTP.begin(); } void AREST_init(void) { // Определяем имя name и ИД ID устройства aREST rest.set_id("1"); rest.set_name("aRest"); // Запускаем сервер SERVERaREST.begin(); } //Здесь функции для aREST обработки // Отправка кода через IRremote int irControl(String command) { // Get state from command unsigned long state = command.toInt(); irsend.sendNEC(state, 36); return 1; } // Здесь функции для работы с файловой системой String getContentType(String filename) { if (HTTP.hasArg("download")) return "application/octet-stream"; else if (filename.endsWith(".htm")) return "text/html"; else if (filename.endsWith(".html")) return "text/html"; else if (filename.endsWith(".css")) return "text/css"; else if (filename.endsWith(".js")) return "application/javascript"; else if (filename.endsWith(".png")) return "image/png"; else if (filename.endsWith(".gif")) return "image/gif"; else if (filename.endsWith(".jpg")) return "image/jpeg"; else if (filename.endsWith(".ico")) return "image/x-icon"; else if (filename.endsWith(".xml")) return "text/xml"; else if (filename.endsWith(".pdf")) return "application/x-pdf"; else if (filename.endsWith(".zip")) return "application/x-zip"; else if (filename.endsWith(".gz")) return "application/x-gzip"; return "text/plain"; } bool handleFileRead(String path) { if (path.endsWith("/")) path += "index.htm"; String contentType = getContentType(path); String pathWithGz = path + ".gz"; if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { if (SPIFFS.exists(pathWithGz)) path += ".gz"; File file = SPIFFS.open(path, "r"); size_t sent = HTTP.streamFile(file, contentType); file.close(); return true; } return false; } void handleFileUpload() { if (HTTP.uri() != "/edit") return; HTTPUpload& upload = HTTP.upload(); if (upload.status == UPLOAD_FILE_START) { String filename = upload.filename; if (!filename.startsWith("/")) filename = "/" + filename; fsUploadFile = SPIFFS.open(filename, "w"); filename = String(); } else if (upload.status == UPLOAD_FILE_WRITE) { //DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize); if (fsUploadFile) fsUploadFile.write(upload.buf, upload.currentSize); } else if (upload.status == UPLOAD_FILE_END) { if (fsUploadFile) fsUploadFile.close(); } } void handleFileDelete() { if (HTTP.args() == 0) return HTTP.send(500, "text/plain", "BAD ARGS"); String path = HTTP.arg(0); if (path == "/") return HTTP.send(500, "text/plain", "BAD PATH"); if (!SPIFFS.exists(path)) return HTTP.send(404, "text/plain", "FileNotFound"); SPIFFS.remove(path); HTTP.send(200, "text/plain", ""); path = String(); } void handleFileCreate() { if (HTTP.args() == 0) return HTTP.send(500, "text/plain", "BAD ARGS"); String path = HTTP.arg(0); if (path == "/") return HTTP.send(500, "text/plain", "BAD PATH"); if (SPIFFS.exists(path)) return HTTP.send(500, "text/plain", "FILE EXISTS"); File file = SPIFFS.open(path, "w"); if (file) file.close(); else return HTTP.send(500, "text/plain", "CREATE FAILED"); HTTP.send(200, "text/plain", ""); path = String(); } void handleFileList() { if (!HTTP.hasArg("dir")) { HTTP.send(500, "text/plain", "BAD ARGS"); return; } String path = HTTP.arg("dir"); Dir dir = SPIFFS.openDir(path); path = String(); String output = "["; while (dir.next()) { File entry = dir.openFile("r"); if (output != "[") output += ','; bool isDir = false; output += "{\"type\":\""; output += (isDir) ? "dir" : "file"; output += "\",\"name\":\""; output += String(entry.name()).substring(1); output += "\"}"; entry.close(); } output += "]"; HTTP.send(200, "text/json", output); }
Не компилится в IDE 1.6.7
Скорее всего так и есть. Я как то пытался пользоваться новой версией тоже не шло. Поэтому остаюсь пока на 1.6.5. Даже 1.6.6 пока не пробовал.
Кстати я понял почему не компилируется в среде выше 1,6,5
Разработчики почему-то вспомнили про синтаксис языка Си
Все функции нужно объявлять перед setup
По этому ваш код и не компилируются в каком виде есть.
Да, это так. В 1.6.8 версии такой код снова компилируется, но теперь там другие библиотеки валятся. Пока остаюсь на 1.6.5.
В описалове к esp8266 плагину для ардуино написано, что стабильная версия (2.0.0) работает в 1.6.5, а текущая бета (2.1.0-rc1/) в 1.6.7. Поэтому надо либо ардуино поставить версии 1.6.5, либо плагин с гитхаба последней версии скачать.
Тут описание установки: https://github.com/esp8266/Arduino/blob/master/README.md
Кстати в последней версии интересные добавления, касающиеся вывода отладочной инфы. Прямо из среды ардуино можно выбирать какую инфу посылать в серийный порт а какую нет. Причем есть отладка разных методов типа post и т.п. Очень удобно!
Привет!
Очень полезное видео. Как раз сам добрался до wifi manager. Правда все делаю в eclipse. Для меня привычнее.
Очень полезно про обновление прошивки по воздуху.
Есть вопрос. WifiManager работает хорошо, но не получается его вызвать принудительно, когда модуль уже подключился к сети, чтобы переподключить его к другой, например по кнопке:
if ( digitalRead(TRIGGER_PIN) == LOW ) {
WiFiManager wifiManager;
wifiManager.startConfigPortal(“OnDemandAP”);
Serial.println(“connected…yeey :)”);
}
Почему-то виснет модуль на этом.
Было бы интересно увидеть видео на эту тему!
У меня под инфраструктуру умного дома выделена отдельная вайфай сеть, поэтому и вопрос возник.
Спасибо!
Здравствуйте подскажите где найти информацию по работе и этой библиотекой ESP8266WebServer
Нормального описания библиотеки на русском пока нет. Используйте примеры и загляните в файл библиотеки: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WebServer/src/ESP8266WebServer.h
Спасибо, разобрался как работать с ней.
Добрый день!
Подскажите как в этом коде создать GET запрос, для отправки значения на сайт в интернете.
(http://api.thingspeak.com/update?key=123456&field1=14)
Нужно использовать библиотеку ESP8266WebServer или нет?
Доброго времени суток . Подскажите пожалуйста как записать в фаил и читать из него в системе SPIFFS
Здравствуйте. Подскажите способы как обмениваться данными между страницей и контроллером, судя по примеру FSBrowser, получаем данные с помощью javascript функции XMLHttprequest, а отправка через get запрос? может есть еще варианты?
Как раз в примере FSBrowser, javascript функции XMLHttprequest не используется. Там простые HTML страницы. AJAX позволяет обмениваться данными между страницей и контроллером, там как раз javascript функции. Буквально сегодня будет пример об использовании AJAX.
Почему же, может правда примеры разные. В папке data лежит index.htm в нем используется XMLHttprequest.
Вот часть кода из этого страницы:
function loadValues(){
if(!running) return;
var xh = new XMLHttpRequest();
xh.onreadystatechange = function(){
if (xh.readyState == 4){
if(xh.status == 200) {
var res = JSON.parse(xh.responseText);
heap.add(res.heap);
temp.add(res.analog);
digi.add(res.gpio);
if(running) setTimeout(loadValues, reloadPeriod);
} else running = false;
}
};
xh.open(“GET”, “/all”, true);
xh.send(null);
};
Они парсят страницу /all, заведомо подготовленную в скетче контроллера. Но мне пока не понятно как обратно отправить данные, с кнопки например..
Здравствуйте. Вы не подскажете, почему ,при запросе 192.168.1.108/edit в списке файлов обрезаны имена? И при загрузке через /edit именя файлов так же обрезаются….
affixm~1.js
font-a~1.css
fontaw~1.otf
fontaw~1.eot
fontaw~1.svg
fontaw~1.ttf
fontaw~1.wof
fontaw~2.wof
jquery~1.js
Только что проверил у себя нет обрезанных имен. Скетч у вас какой?
Я извиняюсь, не совсем туда написал. Заливаю SDWEBSERVER_V2. esp8266 amica.
Скидываю файлы на sd карту.Захожу через /edit и вижу измененные имена =(
Скорее всего в библиотеке работы с SD картами есть ограничение на имена и расширения. Так как для Arduino такие ограничения были.
Видимо да. Поскольку все имена обрезаны – 8 символов до точки. Но где изменить это в коде, так и не увидел =(
Ограничение в библиотеке. Если это требуется нужно переписывать библиотеку. https://www.arduino.cc/en/Reference/SD
Покопав просторы интернета, выяснилось, что подобное ограничение(8 символов и три символа расширения файла), из – за файловой системы и библиотеки SD. Нашел библиотеку SDFat. Она может работать с длинными именами файлов.Было сказано, что ее можно использовать вместо библиотеки SD. Но после ее применения страницы загружаться перестали, грузится какой – то мусор…..
Пока тупик.
Приветствую!
Можно ли подключить к проекту в IDE уже готовый файл, который в ходе заливки будет положен в SPIFFS, и к которому можно будет обращаться из прошивки?
Вставлять его inline теоретически можно, но сами понимаете – криво.
Вопрос не совсем понятен. С одной стороны можно сделать сервис для загрузки образа диска из веб интерфейса одним файлом. С другой стороны любой файл в файловой системе доступен из скетча. Каждый отдельный файл в файловую систему тоже можно загрузить через web интерфейс.
Здравствуйте. Пробовал загрузить Ваш скетч, на стадии компиляции выдаётся ошибка:
exit status 1
‘HTTP_init’ was not declared in this scope
И подсвечивает в скетче строку:
HTTP_init();
Установки у меня такие:
Arduino: 1.6.8 (Windows 7), Плата:”Generic ESP8266 Module, 80 MHz, 40MHz, DIO, 115200, 4M (1M SPIFFS), ck, Serial, None”
Работает только с IDE 1.6.5 Версия ESP ядра 2.0.0. В более поздних версиях SSDP не работает с Windows в Android устройствах работает. Баг в библиотеке.
WM:
*WM: AutoConnect
*WM: Connecting as wifi client…
*WM: Using last saved values, should be faster
*WM: Connection result:
*WM: 3
*WM: IP Address:
*WM: 192.168.0.7
connected…yeey 🙂
ets Jan 8 2013,rst cause:4, boot mode:(1,7)
wdt reset
выдает в мониторе порта после загрузки, подскажите в чем может быть проблема?
Это происходит с моем сктче? Версия Arduino IDE и esp866 сообщите пожалуйста. Проверю и буду готов ответить.
Cкорее всего у вашей ESP недостатчно флеш памяти. B моем варианте била микросхема winbond 25q80bvsig, а ето 8Mbit(1MB) – 1M(512K SPIFS)
Добрый день.
Подскажите, а как добавить страницу с индикацией состояния? (вывести показания датчиков, состояния реле и т.д.) Т.е как данные от esp прикрутить к html странице?
Добрый день!
Подскажите пожалуйста в чем может быть дело, все работало, но после попытки обновления “по воздуху” произошла ошибка.
Теперь ESP выдает ошибку
exception 29. пробовал перепрошивать, не помогает.
Как с этим можно бороться?
Прошейте прошивкой для очистки. http://esp8266-arduinoide.ru/wp-content/uploads/2016/08/blank4.zip
Спасибо, попробую!
Спасибо большое!
Получилось!
Добрый день !
Arduino ide 1.6.8, библиотека 2.0.0.
Не работает ссылка edit , т.е. загружается ну ничего не отображает, просто рамка отделяющая редактор от списка файлов и строка меню , но никаких надписей и т.п. нет :'( подскажите что не так!
Спасибо автору , на его примерах освоил намного ajax ))
Сделал нечто подобное pytt только через веб интерфейс )))
Попробуйте другой браузер.
Пробовал , итог оказался тот же 🙁 а причину нашел ))) скачал с другого места фалы edit и скрипты , все заработало !
все закомпилил аж в 3х версиях ардуино но все равно не работает, сразу вопрос этому серверу не надо выход в сеть?,подключаешься с любого телефона и управляешь кнопками по вай фай правильно? ,мне нужен именно такой вариант , загружал разгружал ,точку доступа создает,подключается но интерфейс не выводит,что я забыл ещё там сделать?
ещё добавлю модуль рабочий ,проверял но булинке все работает
Такая проблема: после заливки файлов в память ESP обнаружил, что кое-где в этих файлах есть ошибки. Исправив их на компьютере, попытался перезалить, но, как оказалось, остаются старые файлы, то есть копирование без замены. Хорошо, что можно редактировать тексты прямо на ESP. А картинки, архивы как перезаливать?
Сегодня случилось чудо. Я взял здесь скетч и папку data, а потом залил их по инструкции в отладочный “бутерброд” на ESP12-E, недавно приобретенный у китайцев. Сервер запустился и подключился к моему wifi, а ведь я ничего нигде не менял и не прописывал свои ssid и пароль. Я просто сразу не нашел куда их прописать и попробовал просто так как было. Теперь я в недоумении – откуда это чудо берет данные моей сети? Я, правда, перед этим заливал туда другие примеры тоже с сервером и криво .
Блин, такая же фигня произошла… Сидел голову ломал, откуда. Решил, что так как прежде указывал переменные с именем и паролем точки доступа, они сохранились либо в библиотеке либо как то менеджер плат на себя взял эту функцию… надо бы поразмыслить)
Подскажите как в редакторе edit.htm сохранять изменения?
ctrl+s записывать и редактировать можно только не сжатые файлы.
Подскажи пожалуйста, не компилируется твой скетч:
C:\Users\anton\Downloads\WiFiManager-IR-FS\WiFiManager-IR-FS.ino:6:72: fatal error: WiFiManager.h: No such file or directory
#include //https://github.com/tzapu/WiFiManager
compilation terminated.
При этом файлик по ссылки https://github.com/tzapu/WiFiManager
я скачивал, WiFiManager.h куда только не клал…
Вроде разобрался, библиотеки надо подключать оказывается:) А я не знал как это проделывать в среде Arduino (
Здравствуйте! Спасибо большое за то что делитесь полезной информацией. Очень понравилась идея обновления прошивки, через web интерфейс. Все делаю по инструкции, но почему-то прошивка не завершается. Делаю экспорт бинарного файла, создается файл объемом 367kb , при попытке обновить прошивку процесс зависает.
Вот что в терминале:
Update: SMART_ROOM_AJAX.ino.nodemcu.bin
sleep disable
Update Success: 374944
Rebooting…
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 3656, room 16
tail 8
chksum 0x0c
csum 0x0c
v9c56ed1f
@cp:0
ld
e:
ets Jan 8 2013,rst cause:3, boot mode:(3,6)
ets_main.c
Контроллер перестает отвечать, опять загружаю прошивку через Arduino IDE, все работает.
У вас на сайте, нашел файл blank4.bin (объем 4096kb) и попробовал его “скормить” через web интерфейс и все получилось.
Получается, что дело в бинарном файле, который я экспортирую из Arduino IDE (версия Arduino IDE 1.8.12)? Интересно, как создан файл blank4.bin и его отличие от того, что я экспортирую?
Спасибо!
Так и не удалось обновить скетч по воздуху, ни через OTA Arduino IDE ни через web. Чтение log показало, что файл blank4.bin просто не влазит по размеру и прошивка прерывается, и просто создавалась иллюзия.
Переключение параметров памяти DOUT-QOUT тоже не дает результатов.
Прошивка самого контроллера, тоже не помогла.
Решил проблему установкой платформы управления ESP 8266 версии 2.5.1. в менеджере плат.