Der Sketch für den Bme280 Innensensor passend zum Aussensensor übersichtlich aufgeteilt in Tabs.
Innensensor.ino
// ****************************************************************
// Sketch Esp8266 Innen Klimasensor Deep Sleep Modular(Tab)
// created: Jens Fleischer, 2019-09-07
// last mod: Jens Fleischer, 2020-04-19
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 / 2.5.2 / 2.6.3 / 2.7.1
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
Copyright (c) 2019 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.
*******************************************************************/
// Der WebServer Tab ist der Haupt Tab mit "setup" und "loop".
// #include <FS.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.
// Inklusive Arduino OTA-Updates
/**************************************************************************************/
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h> // https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html
#include <FS.h>
ESP8266WebServer server(80);
char file[sizeof(__FILE__)] = __FILE__; // Dateiname für den Admin Tab
uint32_t lastResponce;
String outside = "nan";
void setup() {
Serial.begin(115200);
delay(100);
Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
(__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
spiffs();
Connect();
admin();
bme280();
server.on("/aussenklima", []() { // Emfängt die Werte und schickt die Antwort zum Aussensensor
if (server.arg(0) != "") {
outside = (server.arg(0));
server.send(200, "text/plain", "OK" );
lastResponce = millis() / 6e4;
}
});
ArduinoOTA.begin();
server.begin();
}
void loop() {
ArduinoOTA.handle();
server.handleClient();
if (millis() < 0x2FFF || millis() > 0xFFFFF0FF) runtime();
}
Admin.ino
// ****************************************************************
// Sketch Esp8266 Admin Modular(Tab)
// created: Jens Fleischer, 2018-05-09
// last mod: Jens Fleischer, 2021-06-09
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 / 2.5.2 / 2.6.3
// Geprüft: von 1MB bis 16MB Flash
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Switch, Sonoff Dual
/******************************************************************
Copyright (c) 2018 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 Admin sollte als Tab eingebunden werden.
// #include "FS.h" #include müssen im Haupttab aufgerufen werden
// Die Funktionalität des ESP8266 Webservers ist erforderlich.
// Die Spiffs.ino muss im ESP8266 Webserver enthalten sein
// Funktion "admin();" muss im setup() nach spiffs() aber vor dem Verbindungsaufbau aufgerufen werden.
// Die Funktion "runtime();" muss mindestens zweimal innerhalb 49 Tage aufgerufen werden.
// Entweder durch den Client(Webseite) oder zur Sicherheit im "loop();"
/**************************************************************************************/
const char* const PROGMEM flashChipMode[] = {"QIO", "QOUT", "DIO", "DOUT", "Unbekannt"};
void admin() { // Funktionsaufruf "admin();" muss im Setup eingebunden werden
File file = SPIFFS.open("/config.json", "r");
if (file) {
String newhostname = file.readStringUntil('\n');
if (newhostname != "") {
WiFi.hostname(newhostname.substring(1, newhostname.length() - 1));
file.close();
ArduinoOTA.setHostname(WiFi.hostname().c_str());
}
}
server.on("/admin/renew", handlerenew);
server.on("/admin/once", handleonce);
server.on("/reconnect", []() {
server.send(204, "", "");
WiFi.reconnect();
});
server.on("/restart", []() {
server.send(204, "", "");
//speichern(); //Wenn Werte vor dem Neustart gespeichert werden sollen
ESP.restart();
});
}
//Es kann entweder die Spannung am ADC-Pin oder die Modulversorgungsspannung (VCC) ausgegeben werden.
void handlerenew() { // Um die am ADC-Pin anliegende externe Spannung zu lesen, verwende analogRead (A0)
server.send(200, "application/json", "[\"" + runtime() + "\",\"" + WiFi.RSSI() + "\",\"" + analogRead(A0) + "\"]"); // Json als Array
}
/*
ADC_MODE(ADC_VCC);
void handlerenew() { // Zum Lesen der Modulversorgungsspannung (VCC), verwende ESP.getVcc()
server.send(200, "application/json", "[\"" + runtime() + "\",\"" + WiFi.RSSI() + "\",\"" + ESP.getVcc() / 1024.0 + " V" + "\"]"); // Json als Array
}
*/
void handleonce() {
if (server.arg(0) != "") {
WiFi.hostname(server.arg(0));
File f = SPIFFS.open("/config.json", "w"); // Datei zum schreiben öffnen
f.printf("\"%s\"\n", WiFi.hostname().c_str());
f.close();
}
if (strchr(file, '/') || strchr(file, '\\')) {
char *pos = strrchr((file), strstr (file, "\\") ? '\\' : '/'); *pos = '\0';
char* ptr = strtok(file, "\\/");
while (ptr != NULL) {
strcpy(file, ptr);
ptr = strtok(NULL, "\\/");
}
}
else if (strchr(file, '.')) {
char * pos = strchr(file, '.'); *pos = '\0';
}
String temp = "{\"File\":\"" + static_cast<String>(file) + "\", \"Build\":\"" + static_cast<String>(__DATE__) + " " + static_cast<String>(__TIME__) +
"\", \"SketchSize\":\"" + formatBytes(ESP.getSketchSize()) + "\", \"SketchSpace\":\"" + formatBytes(ESP.getFreeSketchSpace()) +
"\", \"LocalIP\":\"" + WiFi.localIP().toString() + "\", \"Hostname\":\"" + WiFi.hostname() + "\", \"SSID\":\"" + WiFi.SSID() +
"\", \"GatewayIP\":\"" + WiFi.gatewayIP().toString() + "\", \"Channel\":\"" + WiFi.channel() + "\", \"MacAddress\":\"" + WiFi.macAddress() +
"\", \"SubnetMask\":\"" + WiFi.subnetMask().toString() + "\", \"BSSID\":\"" + WiFi.BSSIDstr() +
"\", \"ClientIP\":\"" + server.client().remoteIP().toString() + "\", \"DnsIP\":\"" + WiFi.dnsIP().toString() +
"\", \"ResetReason\":\"" + ESP.getResetReason() + "\", \"CpuFreqMHz\":\"" + F_CPU / 1000000 + "\", \"FreeHeap\":\"" + formatBytes(ESP.getFreeHeap()) +
"\", \"ChipSize\":\"" + formatBytes(ESP.getFlashChipSize()) + "\", \"ChipSpeed\":\"" + ESP.getFlashChipSpeed() / 1000000 +
"\", \"ChipMode\":\"" + flashChipMode[ESP.getFlashChipMode()] + "\", \"IdeVersion\":\"" + ARDUINO +
"\", \"CoreVersion\":\"" + ESP.getCoreVersion() + "\", \"SdkVersion\":\"" + ESP.getSdkVersion() + "\"}";
server.send(200, "application/json", temp); // Json als Objekt
}
String runtime() {
static uint8_t rolloverCounter;
static uint32_t previousMillis;
uint32_t currentMillis {millis()};
if (currentMillis < previousMillis) rolloverCounter++; // prüft Millis Überlauf
previousMillis = currentMillis;
uint32_t sec {(0xFFFFFFFF / 1000) * rolloverCounter + (currentMillis / 1000)};
char buf[20];
snprintf(buf, sizeof(buf), "%*.d %.*s %02d:%02d:%02d",
sec < 86400 ? 0 : 1, sec / 86400, sec < 86400 ? 0 : sec >= 172800 ? 4 : 3, "Tage", sec / 3600 % 24, sec / 60 % 60, sec % 60);
return buf;
}
Gib hier die virtuelle Höhe in Meter über Meeresspiegel für deinem Standort ein.
Bme280.ino
// ****************************************************************
// Sketch Esp8266 Bme280 Modular(Tab)
// created: Jens Fleischer, 2018-06-03
// last mod: Jens Fleischer, 2018-09-29
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266, Bme280, 2 x 4k7 Ohm Widerstand
// SCL an D1 = GPIO5
// SDA an D2 = GPIO4
// 4k7 Ohm Widerstand von VCC auf D1
// 4k7 Ohm Widerstand von VCC auf D2
// Software: Esp8266 Arduino Core 2.4.2 / 2.5.2 / 2.6.3
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
Copyright (c) 2018 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 Bme280 sollte als Tab eingebunden werden.
// #include <ESP8266WebServer.h> muss im Haupttab aufgerufen werden
// Die Funktionalität des ESP8266 Webservers ist erforderlich.
// Die Funktion "bme280();" muss im Setup aufgerufen werden.
// Gib die Höhe in Meter über Meeresspiegel an deinem Standort an
/**************************************************************************************/
#include <Wire.h>
#include <BME280I2C.h> // Version 2.3 https://www.github.com/finitespace/BME280
const uint16_t altitude = 163; // virtuelle Höhe in Meter über Meeresspiegel an deinem Standort anpassen
const uint16_t warning = 10; // Zeit bis Warnung bei Ausfall des Aussensensor in Minuten einstellen
BME280I2C bme; // Standard : Zwangsmodus, Standby-Zeit = 1000 ms
void bme280() { // Funktionsaufruf "bme280();" muss im Setup eingebunden werden
Wire.begin();
if (!bme.begin()) {
Serial.println("Keinen BME280 Sensor gefunden!");
}
server.on("/bme280", []() {
server.send(200, "application/json", handleBme());
});
}
String handleBme() {
float temp(NAN), hum(NAN), pres(NAN), sealevel;
bme.read(pres, temp, hum, BME280::TempUnit_Celsius, BME280::PresUnit_hPa);
sealevel = (pres / pow(1 - ((0.0065 * altitude) / (temp + (0.0065 * altitude) + 273.15)), 5.257)); // Berechnung relativer Luftdruck
char buf[55]; // Nachkommastellen zwichen "Punkt" und "f" angeben
snprintf(buf, sizeof(buf), "[\"%.1f\",\"%.f\",\"%.f\",\"%d\",\"%s\"]", temp, hum, sealevel, millis() / 6e4 - lastResponce < warning ? false : true, outside.c_str());
return buf;
}
Connect.ino
// ****************************************************************
// Sketch Esp8266 Connect Modular(Tab) mit optischer Anzeige
// created: Jens Fleischer, 2018-04-08
// last mod: Jens Fleischer, 2019-04-14
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 / 2.5.2 / 2.6.3 / 2.7.1
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Dual
/******************************************************************
Copyright (c) 2018 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 Connect sollte als Tab eingebunden werden.
// #include <ESP8266WebServer.h> muss im Haupttab aufgerufen werden
// Die Funktionalität des ESP8266 Webservers ist erforderlich.
// Die Funktion "Connect();" muss im Setup eingebunden werden.
/**************************************************************************************/
//#define CONFIG // Einkommentieren wenn der ESP dem Router die IP mitteilen soll.
#define NO_SLEEP // Auskommentieren wenn der Nodemcu den deep sleep Modus nutzt.
const char* ssid = "Netzwerkname"; // << kann bis zu 32 Zeichen haben
const char* password = "PasswortvomNetzwerk"; // << mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen
#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
void Connect() { // Funktionsaufruf "Connect();" muss im Setup eingebunden werden
byte i = 0;
//WiFi.disconnect(); // nur erforderlich wenn Esp den AP Modus nicht verlassen will
WiFi.persistent(false); // auskommentieren wenn Netzwerkname oder Passwort in den Flash geschrieben werden sollen
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
#ifdef CONFIG
WiFi.config(staticIP, gateway, subnet, dns);
#endif
while (WiFi.status() != WL_CONNECTED) {
#ifdef NO_SLEEP
pinMode(LED_BUILTIN, OUTPUT); // OnBoardLed Nodemcu, Wemos D1 Mini Pro
digitalWrite(LED_BUILTIN, 0);
#endif
delay(500);
digitalWrite(LED_BUILTIN, 1);
delay(500);
Serial.printf(" %d sek\n", ++i);
if (i > 9) {
Serial.print("\nVerbindung zum AP fehlgeschlagen !\n\n");
ESP.deepSleep(300e6); // 5 Minuten Tiefschlaf falls der Router nicht erreichbar ist
}
}
Serial.println("\nVerbunden mit: " + WiFi.SSID());
Serial.println("Esp8266 IP: " + WiFi.localIP().toString());
}
Spiffs.ino
// ****************************************************************
// Sketch Esp8266 Dateiverwaltung Modular(Tab)
// created: Jens Fleischer, 2018-04-01
// last mod: Jens Fleischer, 2019-06-10
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 / 2.5.2 / 2.6.3 / 2.7.1
// Geprüft: von 1MB bis 16MB Flash
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Switch, Sonoff Dual
/******************************************************************
Copyright (c) 2018 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 Spiffs sollte als Tab eingebunden werden.
// #include "FS.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 "spiffs();" muss im Setup aufgerufen werden.
/**************************************************************************************/
const char Header[] PROGMEM = "HTTP/1.1 303 OK\r\nLocation:spiffs.html\r\nCache-Control: no-cache\r\n";
const char Helper[] PROGMEM = R"(<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name="upload"><input type="submit" value="Upload"></form>Lade die spiffs.html hoch.)";
void spiffs() { // Funktionsaufruf "spiffs();" muss im Setup eingebunden werden
Serial.println(SPIFFS.begin() ? "SPIFFS gestartet!" : "Sketch wurde mit \"no SPIFFS\" kompilliert!\n");
server.on("/json", handleList);
server.on("/format", formatSpiffs);
server.on("/upload", HTTP_POST, []() {}, handleUpload);
server.onNotFound([]() {
if (!handleFile(server.urlDecode(server.uri())))
server.send(404, "text/plain", "FileNotFound");
});
}
void handleList() { // Senden aller Daten an den Client
FSInfo fs_info; SPIFFS.info(fs_info); // Füllt FSInfo Struktur mit Informationen über das Dateisystem
Dir dir = SPIFFS.openDir("/"); // Auflistung aller im Spiffs vorhandenen Dateien
String temp = "[";
while (dir.next()) {
if (temp != "[") temp += ',';
temp += "{\"name\":\"" + dir.fileName().substring(1) + "\",\"size\":\"" + formatBytes(dir.fileSize()) + "\"}";
}
temp += ",{\"usedBytes\":\"" + formatBytes(fs_info.usedBytes * 1.05) + "\"," + // Berechnet den verwendeten Speicherplatz + 5% Sicherheitsaufschlag
"\"totalBytes\":\"" + formatBytes(fs_info.totalBytes) + "\",\"freeBytes\":\"" + // Zeigt die Größe des Speichers
(fs_info.totalBytes - (fs_info.usedBytes * 1.05)) + "\"}]"; // Berechnet den freien Speicherplatz + 5% Sicherheitsaufschlag
server.send(200, "application/json", temp);
}
bool handleFile(String&& path) {
if (server.hasArg("delete")) {
SPIFFS.remove(server.arg("delete")); // Datei löschen
server.sendContent(Header);
return true;
}
if (!SPIFFS.exists("/spiffs.html"))server.send(200, "text/html", Helper); // ermöglicht das hochladen der spiffs.html
if (path.endsWith("/")) path += "index.html";
return SPIFFS.exists(path) ? ({File f = SPIFFS.open(path, "r"); server.streamFile(f, contentType(path)); f.close(); true;}) : false;
}
void handleUpload() { // Dateien vom Rechnenknecht oder Klingelkasten ins SPIFFS schreiben
static File fsUploadFile; // Hält den aktuellen Upload
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
if (upload.filename.length() > 30) {
upload.filename = upload.filename.substring(upload.filename.length() - 30, upload.filename.length()); // Dateinamen auf 30 Zeichen kürzen
}
printf("handleFileUpload Name: /%s\n", upload.filename.c_str());
fsUploadFile = SPIFFS.open("/" + server.urlDecode(upload.filename), "w");
} else if (upload.status == UPLOAD_FILE_WRITE) {
printf("handleFileUpload Data: %u\n", upload.currentSize);
if (fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize);
} else if (upload.status == UPLOAD_FILE_END) {
if (fsUploadFile)
fsUploadFile.close();
printf("handleFileUpload Size: %u\n", upload.totalSize);
server.sendContent(Header);
}
}
void formatSpiffs() { // Formatiert den Speicher
SPIFFS.format();
server.sendContent(Header);
}
const String formatBytes(size_t const& bytes) { // lesbare Anzeige der Speichergrößen
return (bytes < 1024) ? String(bytes) + " Byte" : (bytes < (1024 * 1024)) ? String(bytes / 1024.0) + " KB" : String(bytes / 1024.0 / 1024.0) + " MB";
}
const String &contentType(String& filename) { // ermittelt den Content-Typ
if (filename.endsWith(".htm") || filename.endsWith(".html")) filename = "text/html";
else if (filename.endsWith(".css")) filename = "text/css";
else if (filename.endsWith(".js")) filename = "application/javascript";
else if (filename.endsWith(".json")) filename = "application/json";
else if (filename.endsWith(".png")) filename = "image/png";
else if (filename.endsWith(".gif")) filename = "image/gif";
else if (filename.endsWith(".jpg")) filename = "image/jpeg";
else if (filename.endsWith(".ico")) filename = "image/x-icon";
else if (filename.endsWith(".xml")) filename = "text/xml";
else if (filename.endsWith(".pdf")) filename = "application/x-pdf";
else if (filename.endsWith(".zip")) filename = "application/x-zip";
else if (filename.endsWith(".gz")) filename = "application/x-gzip";
else filename = "text/plain";
return filename;
}
bool freeSpace(uint16_t const& printsize) { // Funktion um beim speichern in Logdateien zu prüfen ob noch genügend freier Platz verfügbar ist.
FSInfo fs_info; SPIFFS.info(fs_info); // Füllt FSInfo Struktur mit Informationen über das Dateisystem
//printf("Funktion: %s meldet in Zeile: %d FreeSpace: %s\n",__PRETTY_FUNCTION__,__LINE__,formatBytes(fs_info.totalBytes - (fs_info.usedBytes * 1.05)).c_str());
return (fs_info.totalBytes - (fs_info.usedBytes * 1.05) > printsize) ? true : false;
}
admin.html
<!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de -->
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
<title>ESP8266 Admin</title>
<script>
window.addEventListener('load', () => {
renew(),once();
let output = document.querySelector('#note');
let button = document.querySelectorAll('button');
let span = document.querySelectorAll('#right span');
button[0].addEventListener('click', () => {
window.location = '/spiffs.html';
});
button[1].addEventListener('click', () => {
window.location = '/';
});
button[2].addEventListener('click', check.bind(this, document.querySelector('input')));
button[3].addEventListener('click', re.bind(this, 'reconnect'));
button[4].addEventListener('click', () => {
if (confirm('Bist du sicher!')) re('restart');
});
function once(arg1,arg2) {
fetch('/admin/once', {
method: 'POST',
body: arg1
}).then( (resp) => {
return resp.json();
}).then( (obj) => {
output.innerHTML = '';
output.classList.remove('note');
document.querySelector('form').reset();
if (arg1 == undefined) myIv = setInterval(renew, 1000);
if (arg2 == 'reconnect') re(arg2);
span[3].innerHTML = obj['File'];
span[4].innerHTML = obj['Build'];
span[5].innerHTML = obj['SketchSize'];
span[6].innerHTML = obj['SketchSpace'];
span[7].innerHTML = obj['LocalIP'];
span[8].innerHTML = obj['Hostname'];
span[9].innerHTML = obj['SSID'];
span[10].innerHTML = obj['GatewayIP'];
span[11].innerHTML = obj['Channel'];
span[12].innerHTML = obj['MacAddress'];
span[13].innerHTML = obj['SubnetMask'];
span[14].innerHTML = obj['BSSID'];
span[15].innerHTML = obj['ClientIP'];
span[16].innerHTML = obj['DnsIP'];
span[17].innerHTML = obj['ResetReason'];
span[18].innerHTML = obj['CpuFreqMHz'] + " MHz";
span[19].innerHTML = obj['FreeHeap'];
span[20].innerHTML = obj['ChipSize'];
span[21].innerHTML = obj['ChipSpeed'] + " MHz";
span[22].innerHTML = obj['ChipMode'];
span[23].innerHTML = obj['IdeVersion'].replace(/(\d)(\d)(\d)(\d)/,obj['IdeVersion'][3]!=0 ? '$1.$3.$4' : '$1.$3.');
span[24].innerHTML = obj['CoreVersion'].replace(/_/g,'.');
span[25].innerHTML = obj['SdkVersion'];
}).catch(function(err) {
re();
});
}
function renew() {
fetch('admin/renew').then( (resp) => {
return resp.json();
}).then( (array) => {
array.forEach((x, i) => {
span[i].innerHTML = x
});
});
}
function check(inObj) {
!inObj.checkValidity() ? (output.innerHTML = inObj.validationMessage, output.classList.add('note')) : (once(inObj.value, 'reconnect'));
}
function re(arg) {
clearInterval(myIv);
fetch(arg);
output.classList.add('note');
if (arg == 'restart') {
output.innerHTML = 'Der Server wird neu gestartet. Die Daten werden in 15 Sekunden neu geladen.';
setTimeout(once, 15000);
}
else if (arg == 'reconnect'){
output.innerHTML = 'Die WiFi Verbindung wird neu gestartet. Daten werden in 10 Sekunden neu geladen.';
setTimeout(once, 10000);
}
else {
output.innerHTML = 'Es ist ein Verbindungfehler aufgetreten. Es wird versucht neu zu verbinden.';
setTimeout(once, 3000);
}
}
});
</script>
</head>
<body>
<h1>ESP8266 Admin Page</h1>
<main>
<aside id="left">
<span>Runtime ESP:</span>
<span>WiFi RSSI:</span>
<span>ADC/VCC:</span>
<span>Sketch Name:</span>
<span>Sketch Build:</span>
<span>SketchSize:</span>
<span>FreeSketchSpace:</span>
<span>IPv4 Address:</span>
<span>Hostname:</span>
<span>Connected to:</span>
<span>Gateway IP:</span>
<span>Channel:</span>
<span>MacAddress:</span>
<span>SubnetMask:</span>
<span>BSSID:</span>
<span>Client IP:</span>
<span>DnsIP:</span>
<span>Reset Ground:</span>
<span>CPU Freq:</span>
<span>FreeHeap:</span>
<span>FlashSize:</span>
<span>FlashSpeed:</span>
<span>FlashMode:</span>
<span>Arduino IDE Version:</span>
<span>Esp Core Version:</span>
<span>SDK Version:</span>
</aside>
<aside id="right">
<span>0</span>
<div>
<span></span>
dBm
</div>
<span>0</span>
<span>?</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>?</span>
<span>?</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>?</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
<span>0</span>
</aside>
</main>
<div>
<button>Spiffs</button>
<button>Startseite</button>
</div>
<div id="note"></div>
<div>
<form>
<input placeholder=" neuer Hostname" pattern="([A-Za-z0-9\-]{1,32})" title="Es dürfen nur Buchstaben
(a-z, A-Z), Ziffern (0-9) und Bindestriche (-) enthalten sein. Maximal 32 Zeichen" required>
<button type="button">Name Senden</button>
</form>
</div>
<div>
<button>WiFi Reconnect</button>
<button>ESP Restart</button>
</div>
</body>
</html>
klima.html
<!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de -->
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
<title>Innen und Aussen Klimadaten</title>
<script>
function renew() {
fetch('/bme280').then(function (response) {
return response.json();
}).then(function (array) {
const elem = document.querySelectorAll('span');
elem[0].innerHTML = array[0] != 'nan' ? array[0] + '°C' : '---------';
elem[1].innerHTML = array[0] != 'nan' ? array[1] + ' %' : 'Fehler';
elem[2].innerHTML = array[0] != 'nan' ? array[2] + ' hPa' : '---------';
array[3] != '0' ? elem[3].classList.add('warn') : elem[3].classList.remove('warn');
elem[4].innerHTML = array[4] != 'nan' ? array[4] + '°C' : '---------';
elem[5].innerHTML = array[4] != 'nan' ? array[5] + ' %' : 'Fehler';
elem[6].innerHTML = array[4] != 'nan' ? array[6] + ' hPa' : '---------';
});
}
document.addEventListener('DOMContentLoaded', renew);
setInterval(renew, 1000)
</script>
<style>
body {
padding: 10px;
font-size: 3em;
}
aside {
align-items: center;
background-color: black;
margin-bottom: 0.5em;
width: 290px;
height: 180px;
border: .15em solid #aeaeab;
box-shadow: 5px 10px 5px rgba(0, 0, 0, 0.7);
border-radius: .2em;
}
aside span {
color: #02fc07;
position: relative;
top: 0.2em;
left: .1em;
font-weight: bold;
}
.warn {
animation-name: blinker;
animation-duration: 1s;
animation-iteration-count: infinite;
}
@keyframes blinker {
50% { color: red;}
}
</style>
</head>
<body>
Innenklima
<aside>
<span></span>
<span></span>
<span></span>
</aside>
<span>Aussenklima</span>
<aside>
<span></span>
<span></span>
<span></span>
</aside>
</body>
</html>
spiffs.html
<!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de -->
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
<title>Esp8266 Datei Manager</title>
<script>
document.addEventListener('DOMContentLoaded', () => {
let myList = document.querySelector('main');
fetch('json').then( (response) => {
return response.json();
}).then((json) => {
for (var i = 0; i < json.length - 1; i++) {
let dir = `<li><a href ="${json[i].name}">${json[i].name}</a><small> ${json[i].size}</small><a href ="${json[i].name}"download="${json[i].name}"> Download </a>`;
if (json[i].name != 'spiffs.html') dir += `or <a href ="${json[i].name}?delete=/${json[i].name}">Delete </a>`;
myList.insertAdjacentHTML('beforeend', dir);
}
myList.insertAdjacentHTML('beforeend', `<li><b>SPIFFS</b> belegt ${json[i].usedBytes} von ${json[i].totalBytes}`);
free = json[i].freeBytes;
});
fs.addEventListener('change', () => {
for (var bytes = 0, j = 0; j < event.target.files.length; j++) bytes += event.target.files[j].size;
for (var output = `${bytes} Byte`, i = 0, circa = bytes / 1024; circa > 1; circa /= 1024) {
output = circa.toFixed(2) + [' KB', ' MB', ' GB'][i++];
}
if (bytes > free) {
si.innerHTML = `<li><b> ${output}</b> <strong style="color: red;"> Ungenügend Speicher frei </strong></li>`;
up.setAttribute('disabled', 'disabled');
}
else {
si.innerHTML = `<li><b>Dateigröße:</b> ${output} </li>`;
up.removeAttribute('disabled');
}
});
btn.addEventListener('click', () => {
if (!confirm(`Wirklich formatieren? Alle Daten gehen verloren.\nDu musst anschließend spiffs.html wieder laden.`)) event.preventDefault();
});
});
</script>
</head>
<body>
<h2>ESP8266 Datei Manager</h2>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input id="fs" type="file" name="upload[]" multiple>
<input id="up" type="submit" value="Upload" disabled>
</form>
<div>
<span id="si"></span>
<main></main>
</div>
<form action="/format" method="POST"><input id="btn" type="submit" value="Format SPIFFS"></form>
</body>
</html>
style.css
/* For more information visit:https://fipsok.de */
body {
font-family: sans-serif;
background-color: #87cefa;
display: flex;
flex-flow: column;
align-items: center;
}
h1,h2 {
color: #e1e1e1;
text-shadow: 2px 2px 2px black;
}
li {
background-color: #feb1e2;
list-style-type: none;
margin-bottom: 10px;
padding: 2px 5px 1px 0;
box-shadow: 5px 5px 5px rgba(0,0,0,0.7);
}
li a:first-child, li b:first-child {
background-color: #8f05a5;
font-weight: bold;
color: white;
text-decoration:none;
padding: 2px 5px;
text-shadow: 2px 2px 1px black;
}
input {
height:35px;
font-size:14px;
}
h1 + main {
display: flex;
}
aside {
display: flex;
flex-direction: column;
padding: 0.2em;
}
#left {
align-items:flex-end;
text-shadow: 0.5px 0.5px 1px #757474;
}
.note {
background-color: #fecdee;
padding: 0.5em;
margin-top: 1em;
text-align: center;
max-width: 320px;
border-radius: 0.5em;
}
[type=submit] {
height:40px;
font-size: 16px;
}
[value*=Format] {
margin-top: 1em;
box-shadow: 5px 5px 5px rgba(0,0,0,0.7);
}
button {
height:40px;
width:130px;
background-color: #7bff97;
font-size:16px;
margin-top: 1em;
box-shadow: 5px 5px 5px rgba(0,0,0,0.7);
}
form [title] {
background-color: skyblue;
font-size: 16px;
width: 125px;
}