Moin zusammen,
habe gerade ein seltsames Problem in Verbindung mit dem Filesystem Manager von Fips.
Immer wenn ich auf die IP-Adresse meines Wemos D1 zugreife färbt sich meine WS2812 hellgrün. Sobald die Webseite aufgebaut ist, ist die LED wieder aus und ändert die Farbe erst dann wieder auf ein helles grün wenn ich etwas am Filesystem mache. Woran kann das liegen?
WS2812 ist an D7 und wird mit 3V3 am Wemos versorgt.
Haupttab
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h> // https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html
#include <LittleFS.h> // Library für Dateisystem LittleFS
#include <DNSServer.h>
#include <ArduinoJson.h>
#include "FastLED.h"
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Anzahl der LEDs für die FastLED Lib festlegen
#define ANZAHL_LEDS 1 // Weil an 1er LED-Stripe angeschlossen
#define LED_PIN 13 // D7 am Wemos
CRGB leds[ANZAHL_LEDS];
// Dein Tankerkoenig ApiKey und die abzufragende TankstellenID
String TankerkoenigApiKey = "geheim";
String TankstellenID = "geheim";
// Ist der Preis keiner dieser Variable soll die LED bunt blinken (float ist zu ungenau, char array wäre besser, dann funktioniert das eigentlich definierte gleich oder kleiner als auch...)
float preisalarm = 1.53;
const char *host = "creativecommons.tankerkoenig.de";
const uint16_t port = 443;
// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
const String url = "https://creativecommons.tankerkoenig.de/json/detail.php?id=" + TankstellenID + "&apikey=" + TankerkoenigApiKey;
// *INDENT-OFF*
const char cert_XSRG_ROOT_X1 [] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)CERT";
// *INDENT-ON*
X509List cert(cert_XSRG_ROOT_X1);
uint32_t lastTime;
const uint32_t intervall = 1000UL * 60 * 5; // mindestens 5 Minuten
// Aktiviert LED im loop
bool ledalarm = false;
ESP8266WebServer server(80);
const byte DNS_PORT = 53;
DNSServer dnsServer;
void configCA() {
client.setTrustAnchors(&cert);
Serial.println("Single CA");
}
int abfrage() {
Serial.print("Connecting to ");
Serial.println(host);
if (!client.connect(host, port)) {
Serial.println("Connection failed");
return -1;
}
lastTime = millis();
HTTPClient http;
Serial.print("[HTTPS] begin...\n");
if (http.begin(client, url)) {
Serial.print("[HTTPS] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String jsonBuffer = http.getString();
Serial.println(jsonBuffer);
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, jsonBuffer);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return -2;
}
bool isOk = doc["ok"];
if (!isOk) {
String msg = doc["message"];
Serial.println(msg);
return -5;
}
JsonObject station = doc["station"];
String name = station["name"];
Serial.println(name);
bool open = station["isOpen"];
Serial.println(open ? "offen" : "geschlossen");
float station_e10 = station["e10"];
if (open == true) {
Serial.print("E10: \t\t");
Serial.println(station_e10, 3);
display.clearDisplay();
display.setCursor(0, 10);
display.setTextSize(1);
display.println("Benzinpreis Super E10");
display.println();
display.setTextSize(4);
display.println(station_e10, 3);
display.display();
if (station_e10 <= preisalarm) {
Serial.println("Preisalarm hat zugeschlagen");
ledalarm = true;
} else {
Serial.println("Preisalarm hat nicht zugeschlagen");
ledalarm = false;
}
} else {
display.clearDisplay();
display.setCursor(0, 10);
display.setTextSize(1);
display.println("Tankstelle ist geschlossen!");
ledalarm = false;
}
}
} else {
Serial.printf("[HTTPS] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
return -3;
}
http.end();
return 0;
} else {
Serial.printf("[HTTPS Unable to connect\n");
return -4;
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
ArduinoOTA.onStart([]() {
//save(); // Wenn Werte vor dem Neustart gespeichert werden sollen
});
ArduinoOTA.begin();
server.begin();
// Initialize the Neopixels and Brightness
FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, ANZAHL_LEDS);
FastLED.setBrightness(80); // Helligkeit 25
// Initalize Display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
delay(500);
setupFS();
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
// Display static text
display.println("Hallo! :)");
display.println();
display.println("Warte auf WLAN...");
display.display();
connectWifi();
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
display.clearDisplay();
display.setCursor(0, 10);
display.setTextSize(1);
display.println("Verbunden! :)");
display.display();
delay(150);
display.clearDisplay();
display.setCursor(0, 10);
// Set time via NTP, as required for x.509 validation
configTime(3 * 3600, 0, "fritz.box", "pool.ntp.org", "time.nist.gov");
Serial.print("Waiting for NTP time sync: ");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2) {
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));
// Initialisierung Root-CA
configCA();
int rc = abfrage();
Serial.print("rc: ");
Serial.println(rc);
if (rc > 0) {
display.clearDisplay();
display.setCursor(0, 10);
display.setTextSize(1);
display.print("Fehler: ");
display.println(rc);
ledalarm = false;
}
}
void loop() {
dnsServer.processNextRequest();
reStation();
ArduinoOTA.handle();
server.handleClient();
if (millis() - lastTime >= intervall) {
int rc = abfrage();
Serial.print("rc: ");
Serial.println(rc);
if (rc > 0) {
display.clearDisplay();
display.setCursor(0, 10);
display.setTextSize(1);
display.print("Fehler: ");
display.println(rc);
ledalarm = false;
}
}
colorled();
}
void colorled() {
if (ledalarm == true) {
uint8_t NUM_LEDS = 1; // Wieviele LEDs sollen blinken
uint8_t thisSpeed = 3; //10
uint8_t deltaHue = 10;
uint8_t thisHue = beat8(thisSpeed, 255);
fill_rainbow(leds, NUM_LEDS, thisHue, deltaHue);
FastLED.show();
} else {
leds[0] = CRGB::Black;
FastLED.show();
}
}
connect.ino
// ****************************************************************
// Sketch Esp8266 Login Manager mit Captive Portal und optischer Anzeige
// created: Jens Fleischer, 2021-01-05
// last mod: Jens Fleischer, 2021-11-29
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.6.3 / 2.7.4 / 3.0.2
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
Copyright (c) 2021 Jens Fleischer. All rights reserved.
This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*******************************************************************/
// Diese Version von Login Manager sollte als Tab eingebunden werden.
// #include <LittleFS.h> #include <ESP8266WebServer.h> müssen im Haupttab aufgerufen werden
// Die Funktionalität des ESP8266 Webservers und des LittleFS Tab ist erforderlich.
// Die Funktion "connectWifi();" muss im Setup eingebunden werden.
// Die Oneboard LED blinkt beim Verbindungsaufbau zum Netzwerk und leuchtet im AP Modus dauerhaft.
// Die Zugangsdaten werden nicht menschenlesbar im Dateisystem gespeichert.
/**************************************************************************************/
/**
Folgendes muss im Webserver Tab vor dem "setup()" eingefügt werden.
#include <DNSServer.h>
const byte DNS_PORT = 53;
DNSServer dnsServer;
Der DNS Server muss im loop aufgerufen werden.
void loop() {
dnsServer.processNextRequest();
reStation();
}
*/
//#define CONFIG // Einkommentieren wenn der ESP dem Router die IP mitteilen soll.
#ifdef CONFIG
IPAddress staticIP(192, 168, 178, 99); // statische IP des NodeMCU ESP8266
IPAddress gateway(192, 168, 178, 1); // IP-Adresse des Router
IPAddress subnet(255, 255, 255, 0); // Subnetzmaske des Netzwerkes
IPAddress dns(192, 168, 178, 1); // DNS Server
#endif
const char HTML[] PROGMEM = R"(<!DOCTYPE HTML>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
button{width:11em;height:2.5em}
body{background: #87cefa; text-align: center;}
</style>
<title>Login Manager</title>
</head>
<body>
<h2>Zugangsdaten</h2>
<form>
<p>
<label>SSID:<br>
<input name="ssid" placeholder="Name vom Netzwerk" required>
</label>
</p>
<p>
<label>Passwort:<br>
<input name="passwort" pattern="[!-~]{8,64}" placeholder="PW vom Netzwerk" required>
</label>
</p>
</form>
<button>
Absenden
</button>
<script>
document.querySelector('button').addEventListener('click', async () =>{
let elem = document.querySelector('form');
if(elem.checkValidity() && document.querySelector('[pattern]').checkValidity()){
let resp = await fetch('/wifisave', {method: 'post', body: new FormData(elem)});
let json = await resp.json();
document.body.innerHTML = json;
}
});
</script>
</body>
</html>)";
const char JSON[] PROGMEM = R"("<h3>Die Zugangsdaten wurden übertragen. Eine Verbindung zum Netzwerk wird hergestellt.</h3>")";
char ssid[33] {" "};
char password[65];
constexpr char key {129};
void connectWifi() {
IPAddress apIP(172, 217, 28, 1);
IPAddress netMsk(255, 255, 255, 0);
File file = LittleFS.open("/wifi.dat", "r");
if (file) {
file.read(reinterpret_cast<uint8_t*>(&ssid), sizeof(ssid));
file.read(reinterpret_cast<uint8_t*>(&password), sizeof(password));
file.close();
for (auto &c : ssid) c ^= key; // Dechiffrierung SSID
for (auto &c : password) c ^= key; // Dechiffrierung Passwort
}
WiFi.disconnect();
WiFi.persistent(false); // Auskommentieren wenn Netzwerkname und Passwort in den Flash geschrieben werden sollen.
WiFi.mode(WIFI_STA); // Station-Modus
WiFi.begin(ssid, password);
#ifdef CONFIG
WiFi.config(staticIP, gateway, subnet, dns);
#endif
uint8_t i {0};
while (WiFi.status() != WL_CONNECTED) {
pinMode(LED_BUILTIN, OUTPUT); // OnBoardLed Nodemcu, Wemos D1 Mini Pro
digitalWrite(LED_BUILTIN, 0); // Led blinkt während des Verbindungsaufbaus
delay(500);
digitalWrite(LED_BUILTIN, 1);
delay(500);
Serial.printf(" %i sek\n", ++i);
if (WiFi.status() == WL_NO_SSID_AVAIL || i > 29) { // Ist die SSID nicht erreichbar, wird ein eigenes Netzwerk erstellt.
digitalWrite(LED_BUILTIN, 0); // Dauerleuchten der Led zeigt den AP Modus an.
WiFi.disconnect();
WiFi.mode(WIFI_AP); // Soft-Access-Point-Modus
Serial.println(PSTR("\nVerbindung zum Router fehlgeschlagen !\nStarte Soft AP"));
WiFi.softAPConfig(apIP, apIP, netMsk);
if (WiFi.softAP("EspConfig")) {
Serial.println(PSTR("Verbinde dich mit dem Netzwerk \"EspConfig\".\n"));
display.clearDisplay();
display.setCursor(0, 10);
display.setTextSize(1);
display.println("WLAN nicht gefunden!");
display.println("");
display.println("Starte Access Point");
display.println("\"EspConfig\"");
display.println("zur Konfiguration...");
display.display();
dnsServer.start(DNS_PORT, "*", apIP);
server.on("/wifisave", HTTP_POST, handleWifiSave);
server.onNotFound(handleRoot);
server.begin();
while (WiFi.status() != WL_CONNECTED) {
server.handleClient();
dnsServer.processNextRequest();
reStation();
}
}
break;
}
}
if (WiFi.status() == WL_CONNECTED) {
Serial.printf(PSTR("\nVerbunden mit: %s\nEsp8266 IP: %s\n"), WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());
}
dnsServer.start(DNS_PORT, "*", apIP);
server.on("/wifisave", HTTP_POST, handleWifiSave);
server.onNotFound(handleRoot);
}
void handleWifiSave() {
if (server.hasArg("ssid") && server.hasArg("passwort")) {
strcpy(ssid, server.arg(0).c_str());
strcpy(password, server.arg(1).c_str());
for (auto &c : ssid) c ^= key; // Chiffrierung SSID
for (auto &c : password) c ^= key; // Chiffrierung Passwort
File file = LittleFS.open("/wifi.dat", "w");
file.write(reinterpret_cast<uint8_t*>(&ssid), sizeof(ssid));
file.write(reinterpret_cast<uint8_t*>(&password), sizeof(password));
file.close();
server.send(200, "application/json", JSON);
delay(500);
connectWifi();
}
}
void handleRoot() {
if (WiFi.status() != WL_CONNECTED) { // Besteht keine Verbindung zur Station wird das Formular gesendet.
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(200, "text/html", HTML);
}
else {
if (!handleFile(server.urlDecode(server.uri()))) {
if (server.urlDecode(server.uri()).endsWith("/")) sendResponce();
server.send(404, "text/plain", "FileNotFound");
}
}
}
void reStation() { // Der Funktionsaufruf "reStation();" sollte im "loop" stehen.
static unsigned long previousMillis; // Nach Stromausfall startet der Esp.. schneller als der Router.
constexpr unsigned long INTERVAL (3e5); // Im AP Modus aller 5 Minuten prüfen ob der Router verfügbar ist.
if (millis() - previousMillis >= INTERVAL) {
previousMillis += INTERVAL;
if (WiFi.status() != WL_CONNECTED) connectWifi();
}
}
LittleFS.ino
// ****************************************************************
// Sketch Esp8266 Filesystem Manager spezifisch sortiert Modular(Tab)
// created: Jens Fleischer, 2020-06-08
// last mod: Jens Fleischer, 2020-12-19
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.7.0 - 3.0.2
// Geprüft: von 1MB bis 2MB Flash
// Getestet auf: Nodemcu
/******************************************************************
Copyright (c) 2020 Jens Fleischer. All rights reserved.
This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*******************************************************************/
// Diese Version von LittleFS sollte als Tab eingebunden werden.
// #include <LittleFS.h> #include <ESP8266WebServer.h> müssen im Haupttab aufgerufen werden
// Die Funktionalität des ESP8266 Webservers ist erforderlich.
// "server.onNotFound()" darf nicht im Setup des ESP8266 Webserver stehen.
// Die Funktion "setupFS();" muss im Setup aufgerufen werden.
/**************************************************************************************/
#include <list>
#include <tuple>
const char WARNING[] PROGMEM = R"(<h2>Der Sketch wurde mit "FS:none" kompilliert!)";
const char HELPER[] PROGMEM = R"(<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name="[]" multiple><button>Upload</button></form>Lade die fs.html hoch.)";
void setupFS() { // Funktionsaufruf "setupFS();" muss im Setup eingebunden werden
LittleFS.begin();
server.on("/format", formatFS);
server.on("/upload", HTTP_POST, sendResponce, handleUpload);
server.onNotFound([]() {
if (!handleFile(server.urlDecode(server.uri())))
server.send(404, "text/plain", "FileNotFound");
});
}
bool handleList() { // Senden aller Daten an den Client
FSInfo fs_info; LittleFS.info(fs_info); // Füllt FSInfo Struktur mit Informationen über das Dateisystem
Dir dir = LittleFS.openDir("/");
using namespace std;
using records = tuple<String, String, int>;
list<records> dirList;
while (dir.next()) { // Ordner und Dateien zur Liste hinzufügen
if (dir.isDirectory()) {
uint8_t ran {0};
Dir fold = LittleFS.openDir(dir.fileName());
while (fold.next()) {
ran++;
dirList.emplace_back(dir.fileName(), fold.fileName(), fold.fileSize());
}
if (!ran) dirList.emplace_back(dir.fileName(), "", 0);
}
else {
dirList.emplace_back("", dir.fileName(), dir.fileSize());
}
}
dirList.sort([](const records & f, const records & l) { // Dateien sortieren
if (server.arg(0) == "1") {
return get<2>(f) > get<2>(l);
} else {
for (uint8_t i = 0; i < 31; i++) {
if (tolower(get<1>(f)[i]) < tolower(get<1>(l)[i])) return true;
else if (tolower(get<1>(f)[i]) > tolower(get<1>(l)[i])) return false;
}
return false;
}
});
dirList.sort([](const records & f, const records & l) { // Ordner sortieren
if (get<0>(f)[0] != 0x00 || get<0>(l)[0] != 0x00) {
for (uint8_t i = 0; i < 31; i++) {
if (tolower(get<0>(f)[i]) < tolower(get<0>(l)[i])) return true;
else if (tolower(get<0>(f)[i]) > tolower(get<0>(l)[i])) return false;
}
}
return false;
});
String temp = "[";
for (auto& t : dirList) {
if (temp != "[") temp += ',';
temp += "{\"folder\":\"" + get<0>(t) + "\",\"name\":\"" + get<1>(t) + "\",\"size\":\"" + formatBytes(get<2>(t)) + "\"}";
}
temp += ",{\"usedBytes\":\"" + formatBytes(fs_info.usedBytes) + // Berechnet den verwendeten Speicherplatz
"\",\"totalBytes\":\"" + formatBytes(fs_info.totalBytes) + // Zeigt die Größe des Speichers
"\",\"freeBytes\":\"" + (fs_info.totalBytes - fs_info.usedBytes) + "\"}]"; // Berechnet den freien Speicherplatz
server.send(200, "application/json", temp);
return true;
}
void deleteRecursive(const String &path) {
if (LittleFS.remove(path)) {
LittleFS.open(path.substring(0, path.lastIndexOf('/')) + "/", "w");
return;
}
Dir dir = LittleFS.openDir(path);
while (dir.next()) {
deleteRecursive(path + '/' + dir.fileName());
}
LittleFS.rmdir(path);
}
bool handleFile(String &&path) {
if (server.hasArg("new")) {
String folderName {server.arg("new")};
for (auto& c : {34, 37, 38, 47, 58, 59, 92}) for (auto& e : folderName) if (e == c) e = 95; // Ersetzen der nicht erlaubten Zeichen
LittleFS.mkdir(folderName);
}
if (server.hasArg("sort")) return handleList();
if (server.hasArg("delete")) {
deleteRecursive(server.arg("delete"));
sendResponce();
return true;
}
if (!LittleFS.exists("fs.html")) server.send(200, "text/html", LittleFS.begin() ? HELPER : WARNING); // ermöglicht das hochladen der fs.html
if (path.endsWith("/")) path += "index.html";
if (path == "/spiffs.html") sendResponce(); // Vorrübergehend für den Admin Tab
return LittleFS.exists(path) ? ({File f = LittleFS.open(path, "r"); server.streamFile(f, mime::getContentType(path)); f.close(); true;}) : false;
}
void handleUpload() { // Dateien ins Filesystem schreiben
static File fsUploadFile;
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
if (upload.filename.length() > 31) { // Dateinamen kürzen
upload.filename = upload.filename.substring(upload.filename.length() - 31, upload.filename.length());
}
printf(PSTR("handleFileUpload Name: /%s\n"), upload.filename.c_str());
fsUploadFile = LittleFS.open(server.arg(0) + "/" + server.urlDecode(upload.filename), "w");
} else if (upload.status == UPLOAD_FILE_WRITE) {
printf(PSTR("handleFileUpload Data: %u\n"), upload.currentSize);
fsUploadFile.write(upload.buf, upload.currentSize);
} else if (upload.status == UPLOAD_FILE_END) {
printf(PSTR("handleFileUpload Size: %u\n"), upload.totalSize);
fsUploadFile.close();
}
}
void formatFS() { // Formatiert das Filesystem
LittleFS.format();
sendResponce();
}
void sendResponce() {
server.sendHeader("Location", "fs.html");
server.send(303, "message/http");
}
const String formatBytes(size_t const& bytes) { // lesbare Anzeige der Speichergrößen
return bytes < 1024 ? static_cast<String>(bytes) + " Byte" : bytes < 1048576 ? static_cast<String>(bytes / 1024.0) + " KB" : static_cast<String>(bytes / 1048576.0) + " MB";
}