diff --git a/Libraries/Adafruit_Sensor-1.1.7.zip b/Libraries/Adafruit_Sensor-1.1.7.zip new file mode 100644 index 0000000..e0ab381 Binary files /dev/null and b/Libraries/Adafruit_Sensor-1.1.7.zip differ diff --git a/Libraries/DHT-sensor-library-1.4.4.zip b/Libraries/DHT-sensor-library-1.4.4.zip new file mode 100644 index 0000000..a1e44b6 Binary files /dev/null and b/Libraries/DHT-sensor-library-1.4.4.zip differ diff --git a/Libraries/ESPAsyncTCP-master.zip b/Libraries/ESPAsyncTCP-master.zip new file mode 100644 index 0000000..2536c6f Binary files /dev/null and b/Libraries/ESPAsyncTCP-master.zip differ diff --git a/Libraries/ESPAsyncWebServer-master.zip b/Libraries/ESPAsyncWebServer-master.zip new file mode 100644 index 0000000..09dfe38 Binary files /dev/null and b/Libraries/ESPAsyncWebServer-master.zip differ diff --git a/Libraries/rc-switch-2.6.4.zip b/Libraries/rc-switch-2.6.4.zip new file mode 100644 index 0000000..9228a52 Binary files /dev/null and b/Libraries/rc-switch-2.6.4.zip differ diff --git a/README.md b/README.md index 75d0652..b324538 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # ESP32_-_Temperature_and_Humidity_Webserver -Webserver running on a ESP32/8266 Device showing data of a connected temperature/humidity sensor. \ No newline at end of file +Webserver running on a ESP32/8266 Device showing data of a connected temperature/humidity sensor. + +## Preferences.h + +Library for ESP8266 can be used from +https://github.com/vshymanskyy/Preferences diff --git a/webserver_temp_hum_ESP32_and_8266.ino b/webserver_temp_hum_ESP32_and_8266.ino new file mode 100644 index 0000000..92b7f85 --- /dev/null +++ b/webserver_temp_hum_ESP32_and_8266.ino @@ -0,0 +1,515 @@ +/** + * + * Date: 2023-02-14 + * Created by: Niklas Mueller + * Inspired by: Rui Santos @ https://randomnerdtutorials.com/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide/ + * +*/ + +// Import required libraries +#ifdef ESP32 +#include + +// For ESP32-PoE +#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT +#define ETH_PHY_POWER 12 +#include +static bool eth_connected = false; + +#elif defined(ESP8266) +#include +#endif + +#include +#include +#include // ESP8266 can be found at: https://github.com/vshymanskyy/Preferences + + + +// ################################################################ +// ### Change the following Settings to match your environment ### +// ################################################################ + +// Replace with your network credentials + +const char* ssid = ""; +const char* password = ""; + +String logoURL = ".../logo.svg"; // Should be Landscape format +String faviconURL = "/favicon.svg"; + +// #define DHTPIN 32 // Digital pin connected to the DHT sensor | ESP32 (G32 -> 32) +#define DHTPIN 4 // Digital pin connected to the DHT sensor | ESP8266 (Number 4 is the D2 PIN) + +// Uncomment the type of sensor in use: +// #define DHTTYPE DHT11 // DHT 11 +#define DHTTYPE DHT22 // DHT 22 (AM2302) +// #define DHTTYPE DHT21 // DHT 21 (AM2301) + +// ################################################################ +// ### Change the Settings above acordingly to your environment ### +// ################################################################ + + +String string_location; +String string_settings; +String string_humidity; +String string_temperature; +String string_initial_password; +String string_new_location; +String string_update_location; + + +String location_of_device; +String admin_password; + +Preferences preferences; +DHT dht(DHTPIN, DHTTYPE); + +// current temperature & humidity, updated in loop() +float t = 0.0; +float tFahrenheit = 0.0; +float h = 0.0; + +// Create AsyncWebServer object on port 80 +AsyncWebServer server(80); + +// Generally, you should use "unsigned long" for variables that hold time +// The value will quickly become too large for an int to store +unsigned long previousMillis = 0; // will store last time DHT was updated +unsigned long previousMillisReboot = 0; // will store last time DHT was updated + +// Updates DHT readings every 10 seconds +const long interval = 10000; +// Reboot ESP every xxx Milli-Seconds +const long intervalReboot = 3600000; + +void loadSettings() { + preferences.begin("base-settings", false); + location_of_device = preferences.getString("location", "No Location found"); + admin_password = preferences.getString("password", "No Password set"); + preferences.end(); +} + + +#ifdef ESP32 +void WiFiEvent(WiFiEvent_t event) +{ + switch (event) { + case SYSTEM_EVENT_ETH_START: + Serial.println("ETH Started"); + //set eth hostname here + ETH.setHostname("esp32-ethernet"); + break; + case SYSTEM_EVENT_ETH_CONNECTED: + Serial.println("ETH Connected"); + break; + case SYSTEM_EVENT_ETH_GOT_IP: + Serial.print("ETH MAC: "); + Serial.print(ETH.macAddress()); + Serial.print(", IPv4: "); + Serial.print(ETH.localIP()); + if (ETH.fullDuplex()) { + Serial.print(", FULL_DUPLEX"); + } + Serial.print(", "); + Serial.print(ETH.linkSpeed()); + Serial.println("Mbps"); + eth_connected = true; + break; + case SYSTEM_EVENT_ETH_DISCONNECTED: + Serial.println("ETH Disconnected"); + eth_connected = false; + break; + case SYSTEM_EVENT_ETH_STOP: + Serial.println("ETH Stopped"); + eth_connected = false; + break; + default: + break; + } +} +#endif + +void setup(){ + // Serial port for debugging purposes + Serial.begin(115200); + dht.begin(); + + // Connect to Wi-Fi + WiFi.begin(ssid, password); + + #ifdef ESP32 + WiFi.onEvent(WiFiEvent); + ETH.begin(); + #endif + + Serial.println("Connecting to WiFi"); + while (WiFi.status() != WL_CONNECTED) { + delay(1000); + Serial.print("."); + } + + Serial.println(""); // Line Break if Connection has been established + + // Print IP and MAC Address + Serial.print("Wifi-MAC: "); + Serial.println(WiFi.macAddress()); + Serial.print("Wifi-IP: "); + Serial.println(WiFi.localIP()); + + #ifdef ESP32 + Serial.print("Eth-MAC: "); + Serial.println(ETH.macAddress()); + Serial.print("Eth-IP: "); + Serial.println(ETH.localIP()); + #endif + + preferences.begin("base-settings", false); + + Serial.print("hasBooted: "); + Serial.println(preferences.getBool("hasBooted", false)); + + if (! preferences.getBool("hasBooted", false)) { + // At first run, set Default Values (Location, Language, ...) + Serial.println("Running first Setup..."); + preferences.clear(); + preferences.putBool("hasBooted", true); + preferences.putString("location", "Default Location"); + preferences.putString("password", "Admin"); + } + + Serial.print("hasBooted: "); + Serial.println(preferences.getBool("hasBooted", false)); + Serial.print("location: "); + Serial.println(preferences.getString("location", "No Location found")); + Serial.print("password: "); + Serial.println(preferences.getString("password", "No Password set")); + + preferences.end(); + + loadSettings(); + + // Defaults to english; Change String here for other Languages + string_location = "Location"; + string_settings = "Settings"; + string_humidity = "Humidity"; + string_temperature = "Temperature"; + string_initial_password = "Initial Password"; + string_new_location = "New Location"; + string_update_location = "Update Location"; + + /* + // German + string_location = "Standort"; + string_settings = "Einstellungen"; + string_humidity = "Luftfeuchtigkeit"; + string_temperature = "Temperatur"; + string_initial_password = "Initial Passwort"; + string_new_location = "Neuer Standort"; + string_update_location = "Standort Aktualisieren"; + */ + + + // Route for root / web page + server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ + + char index_html[] = R"rawliteral( + + + + + + + + ESP Sensor | + + + + + + + + + + +
+ +
+
+


+
+
+ +
+
+
+ + + )rawliteral"; + + request->send(200, "text/html; charset=UTF-8", index_html); + }); + + + // Route for Stylesheet + server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){ + String style_css = ""; + // style_css += " div{ border: 1px solid yellowgreen; }"; + style_css += "#main-content-div {\n\twidth: 70%;\n\tmargin: 0 auto;\n\tdisplay: block;\n}\n"; + style_css += "#menu-div {\n\twidth: 100%;\n\ttext-align: right;\n\tpadding-top: 1em;\n\tpadding-bottom: 1em;\n}\n"; + style_css += "#logo-div {\n\twidth: 100%;\n\tmax-width: 100%;\n\tpadding-top: 1em;\n\tpadding-bottom: 2em;\n\tmargin-bottom: 1em;\n}\n"; + style_css += "#logo-div img {\n\twidth: 100%;\n\tmax-width: 100%;\n}\n"; + style_css += "#control-div {\n\twidth: 40%;\n\tfloat: left;\n\toverflow: hidden;\n\tdisplay: block;\n}\n"; + style_css += "#history-div {\n\twidth: 60%;\n\theight: 300px;\n\toverflow: scroll;\n\tfloat: right;\n\tbackground: lightgoldenrodyellow;\n}\n"; + + request->send(200, "text/css", style_css); + }); + + // Route for Javascript + server.on("/scripts.js", HTTP_GET, [](AsyncWebServerRequest *request){ + char script_js[] = R"rawliteral( + console.debug('ESP Sensor aktiv...'); + + function update_values () { + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + apiResponse = JSON.parse(this.responseText); + console.debug(apiResponse); + + document.title = "ESP Sensor | " + apiResponse["Location"]; + document.getElementById("info-div").innerHTML = "Location: " + apiResponse["Location"]; + document.getElementById("info-div").innerHTML += "

Temperature: " + apiResponse["Temperature"] + " °C | Humidity: " + apiResponse["Humidity"]; + document.getElementById("history-div").innerHTML = "
" + new Date().toString() + " | " + apiResponse["Temperature"] + " °C | Humidity: " + apiResponse["Humidity"] + document.getElementById("history-div").innerHTML; + } + }; + xhttp.open("GET", "/api", true); + xhttp.send(); + } + + document.addEventListener("DOMContentLoaded", function() { + setInterval(update_values, 10000); + }); + + document.addEventListener("DOMContentLoaded", function() { + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + apiResponse = JSON.parse(this.responseText)["result"]; + console.debug(apiResponse); + + var link = document.querySelector("link[rel~='icon']"); + link.href = apiResponse["favicon_url"]; + + var logo = document.getElementById("main_logo"); + logo.src = apiResponse["logo_url"]; + } + }; + xhttp.open("GET", "/settings-backend?function=getSettings", true); + xhttp.send(); + update_values(); + }); + + + function updateLocation() { + var url = "/settings-backend"; + var params = "password=Admin&location=" + document.getElementById("new-location").value; + var xhr = new XMLHttpRequest(); + xhr.open("POST", url, true); + + //Send the proper header information along with the request + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + + xhr.send(params); + update_values(); + } + + )rawliteral"; + + request->send(200, "text/javascript; charset=UTF-8", script_js); + }); + + server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send_P(200, "text/plain", String(t).c_str()); + }); + + server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send_P(200, "text/plain", String(h).c_str()); + }); + + server.on("/settings-backend", HTTP_GET, [](AsyncWebServerRequest *request){ + String tmp; + preferences.begin("base-settings", false); + if (request->hasParam("function", false)) { + if (request->getParam("function")->value() == "getSettings") { + Serial.println("Send Setting Informations"); + tmp = "{\"code\": 200, \"result\": {\"location\": \""+preferences.getString("location", "No Location found")+"\", \"favicon_url\": \""+faviconURL+"\", \"logo_url\": \""+logoURL+"\"}}"; + } else { + Serial.println("Function not found"); + tmp = "{\"code\": 500,\"message\": \"Function not found\"}"; + } + } else { + Serial.println("NO parameter received"); + tmp = "{\"code\": 400,\"message\": \"No Parameters given\"}"; + } + preferences.end(); + request->send(200, "application/json", tmp); + }); + + + server.on("/settings-backend", HTTP_POST, [](AsyncWebServerRequest *request){ + String tmp; + + if (request->hasParam("password", true)) { + + String password = request->getParam("password", true)->value(); + Serial.println("password"); + Serial.println(password); + Serial.println("admin_password"); + Serial.println(admin_password); + + if (strcmp(password.c_str(), admin_password.c_str()) == 0) { + + preferences.begin("base-settings", false); + if (request->hasParam("location", true)) { + preferences.putString("location", request->getParam("location", true)->value()); + } + if (request->hasParam("new-password", true)) { + preferences.putString("password", request->getParam("new-password", true)->value()); + } + preferences.end(); + + Serial.println("Settings updated"); + tmp = "{\"code\": 200,\"message\": \"Settings updated\"}"; + } else { + Serial.println("Password not correct"); + tmp = "{\"code\": 500,\"message\": \"Password not correct\"}"; + } + } else { + Serial.println("Settings not updated"); + tmp = "{\"code\": 400,\"message\": \"No Parameters given\"}"; + } + + loadSettings(); + request->send(200, "application/json", tmp); + }); + + + server.on("/api", HTTP_GET, [](AsyncWebServerRequest *request){ + + String tmp = "{\"" + string_location + "\": \"" + location_of_device + "\", \"" + string_temperature + "\": "; + tmp += String(t).c_str(); + tmp += ", \"" + string_humidity + "\": "; + tmp += String(h).c_str(); + tmp += "}"; + + request->send(200, "application/json", tmp); + }); + + server.on("/prtg-json", HTTP_GET, [](AsyncWebServerRequest *request){ + String tmp = ""; + + tmp += "{\"prtg\": {\"result\": ["; + + tmp += "{\"channel\": \"" + string_temperature + "\","; + tmp += "\"value\": "; + tmp += String(t).c_str(); + tmp += "},"; + + tmp += "{\"channel\": \"" + string_humidity + "\","; + tmp += "\"value\": "; + tmp += String(h).c_str(); + tmp += "}"; + + tmp += "]}}"; + + request->send(200, "application/json", tmp); + }); + + + server.on("/prtg-xml", HTTP_GET, [](AsyncWebServerRequest *request){ + String tmp = ""; + tmp += ""; + + tmp += ""; + tmp += "" + string_temperature + ""; + tmp += "1"; + tmp += "Temperature"; + tmp += ""; + tmp += String(t).c_str(); + tmp += ""; + tmp += ""; + + tmp += ""; + tmp += "" + string_humidity + ""; + tmp += "1"; + tmp += "Percent"; + tmp += ""; + tmp += String(h).c_str(); + tmp += ""; + tmp += ""; + + tmp += ""; + + request->send(200, "text/xml", tmp); + }); + + + server.on("/favicon.svg", HTTP_GET, [](AsyncWebServerRequest *request){ + String tmp = ""; + + tmp += ""; + tmp += ""; + tmp += ""; + + request->send(200, "image/svg+xml", tmp); + }); + + + // Start server + server.begin(); +} + + + + +void loop(){ + unsigned long currentMillis = millis(); + if (currentMillis - previousMillis >= interval) { + // save the last time you updated the DHT values + previousMillis = currentMillis; + // Read temperature as Celsius (the default) + float newT = dht.readTemperature(); + // Read temperature as Fahrenheit (isFahrenheit = true) + //float newT = dht.readTemperature(true); + // if temperature read failed, don't change t value + if (isnan(newT)) { + Serial.println("Failed to read from DHT sensor!"); + } + else { + t = newT; + Serial.print("t: "); + Serial.println(t); + // °F = (°C × 9/5) + 32 + // tFahrenheit = (newT * 9 / 5) + 32; + } + // Read Humidity + float newH = dht.readHumidity(); + // if humidity read failed, don't change h value + if (isnan(newH)) { + Serial.println("Failed to read from DHT sensor!"); + } + else { + h = newH; + Serial.print("h: "); + Serial.println(h); + } + } + + if (currentMillis - previousMillisReboot >= intervalReboot) { + ESP.restart(); + } +}