// Use from 0 to 4. Higher number, more debugging messages and memory usage. //#define _WIFIMGR_LOGLEVEL_ 4 //#define DEBUG 1 #include #include #include "debug.h" #include #include #include #include #include #include #include #define MDNS_NAME "wlanthermometer" #define AP_SSID_CONFIG_NAME "WLANTHERMOMETER-Config" #define AP_CONFIG_PASSWORD "wlanthermometer" #define AP_DATA_RESET_PIN 25 #define TEMP_SENS_PIN 27 #define LCD_I2C_ADDR 0x3f #define LCD_COL 20 #define LCD_ROW 4 #define KRATE_TEMP 5000 #define KRATE_TIME 500 #define KRATE_RESET_AP_DATA 5000 #define MEDIAN_SAMPLES 60 #define ONBOARD_LED 2 #define NTP_TIMEOUT 15000 #define WIFI_CONNECT_TIMEOUT 30 #define CFG_PORTAL_TIMEOUT 90 #define DHTTYPE DHT22 #define FIRST_MIN_MAX 300000 // = 5 min #define HTML_RELOAD_PAGE_SECS 30 LiquidCrystal_I2C lcd(LCD_I2C_ADDR, LCD_COL, LCD_ROW); looper sched; float temp[3]; float hum[3]; float heat[3]; bool led_state; String header; WiFiServer server(80); DHT dht(TEMP_SENS_PIN, DHTTYPE); const uint8_t degree_sign[8] = { B00010, B00101, B00010, B00000, B00000, B00000, B00000, B00000 }; uint8_t add_summertime = 0; bool last_reset_ap_check = false; bool minmax_enabled = false; enum { ACT, MIN, MAX }; void setup() { pinMode(AP_DATA_RESET_PIN, INPUT_PULLDOWN); pinMode(ONBOARD_LED, OUTPUT); Serial.begin(115200); Serial.println(F("WLANThermometer (c)2020 H. Wirtz ")); lcd.init(); lcd.backlight(); lcd.clear(); lcd.noCursor(); lcd.setCursor(2, 0); lcd.print(F("WLAN THERMOMETER")); lcd.setCursor(2, 1); lcd.print(F("(c)parasiTstudio")); WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP WiFiManager wm; lcd.setCursor(0, 2); lcd.print(F("Connecting WiFi... ")); lcd.setCursor(0, 3); lcd.print(F("CFG-AP: 192.168.4.1")); wm.setConnectTimeout(WIFI_CONNECT_TIMEOUT); wm.setConfigPortalTimeout(CFG_PORTAL_TIMEOUT); wm.setBreakAfterConfig(true); if (!wm.autoConnect(AP_SSID_CONFIG_NAME, AP_CONFIG_PASSWORD)) { lcd.setCursor(0, 2); lcd.print(F("Failed ")); DEBUG_MSG("Failed to connect\n"); delay(1000); lcd.setCursor(8, 2); lcd.print(F("- restart")); delay(1000); ESP.restart(); } else { DEBUG_MSG("Connected\n"); if (!MDNS.begin(MDNS_NAME)) { DEBUG_MSG("Error setting up MDNS responder!\n"); } else { DEBUG_MSG("mDNS started.\n"); } lcd.clear(); lcd.setCursor(0, 0); lcd.print(F("Mode WiFi client")); lcd.setCursor(0, 1); lcd.print(WiFi.localIP()); delay(500); } lcd.setCursor(0, 3); lcd.print("Getting time..."); DateTime.setTimeZone(1); DateTime.begin(); /* while (!DateTime.isTimeValid()) { DEBUG_MSG("Failed to get time from server.\n"); DateTime.forceUpdate(); }*/ if (DateTime.isTimeValid()) { if (is_wintertime(DateTime.getTime()) == false) add_summertime = 1; else add_summertime = 0; } // create a degree sign lcd.createChar(0, (uint8_t*)degree_sign); dht.begin(); server.begin(); sched.addJob(show_temperature, KRATE_TEMP); sched.addJob(show_time, KRATE_TIME); sched.addJob(check_reset_ap_data, KRATE_RESET_AP_DATA); get_sensor_data(); temp[MIN] = temp[ACT]; temp[MAX] = temp[ACT]; hum[MIN] = hum[ACT]; hum[MAX] = hum[ACT]; heat[MIN] = heat[ACT]; heat[MAX] = heat[ACT]; lcd.clear(); show_time(); show_temperature(); } void loop() { static uint32_t next_time_check; sched.scheduler(); if (!DateTime.isTimeValid() && millis() - 10000 > next_time_check) { next_time_check = millis(); DateTime.setTimeZone(1); DateTime.forceUpdate(); if (is_wintertime(DateTime.getTime()) == false) add_summertime = 1; else add_summertime = 0; } WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, DEBUG_MSG("New Client.\n"); // print a message out in the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // checking if header is valid // YWRtaW46c3RhYWdhcg== (user:pass) admin:staagar if (header.indexOf("YWRtaW46c3RhYWdhcg==") >= 0) { client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); client.println(""); client.println(""); client.println(""); client.println("Temperatur"); client.print(""); client.println(""); client.println(""); client.println(""); client.println(""); client.println("
"); client.println("

Temperatur

"); client.print("

Aktuell: "); client.print(temp[ACT]); client.println(" °C

"); if (millis() > FIRST_MIN_MAX) { client.print("

Minimum: "); client.print(temp[MIN]); client.print(" °C"); client.print("

\n"); client.print("

Maximum: "); client.print(temp[MAX]); client.print(" °C"); client.println("

"); } client.println("
"); client.println("

Gefühlte Temperatur

"); client.print("

Aktuell: "); client.print(heat[ACT]); client.println(" °C

"); if (millis() > FIRST_MIN_MAX) { client.print("

Minimum: "); client.print(heat[MIN]); client.print(" °C"); client.println("

"); client.print("

Maximum: "); client.print(heat[MAX]); client.print(" °C"); client.println("

"); } client.println("
"); client.println("

Luftfeuchtigkeit

"); client.print("

Aktuell: "); client.print(hum[ACT]); client.println(" %

"); if (millis() > FIRST_MIN_MAX) { client.print("

Minimum: "); client.print(hum[MIN]); client.print(" %"); client.println("

"); client.print("

Maximum: "); client.print(hum[MAX]); client.print(" %"); client.println("

"); } if (DateTime.isTimeValid()) { DateTimeParts p = DateTime.getParts(); char dt[21]; if (is_wintertime(DateTime.getTime()) == false) add_summertime = 1; else add_summertime = 0; client.println("
"); client.print("

"); sprintf(dt, "%02d.%02d.%4d %02d:%02d:%02d", p.getMonthDay(), p.getMonth() + 1, p.getYear(), p.getHours() + add_summertime, p.getMinutes(), p.getSeconds()); client.print(dt); if (add_summertime > 0) client.print(" Sommerzeit"); else client.print(" Winterzeit"); client.println("

"); } client.println("
"); client.println(""); client.println(""); break; } // Wrong user or password, so HTTP request fails... else { client.println("HTTP/1.1 401 Unauthorized"); client.println("WWW-Authenticate: Basic realm=\"Secure\""); client.println("Content-Type: text/html"); client.println(); client.println("Authentication failed"); break; } } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; // Close the connection client.stop(); DEBUG_MSG("Client disconnected.\n\n"); } } void check_reset_ap_data(void) { if (digitalRead(AP_DATA_RESET_PIN) == HIGH && last_reset_ap_check == true) { DEBUG_MSG("Reset AP data\n"); WiFiManager wm; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Resetting AP Data"); delay(2000); wm.resetSettings(); lcd.setCursor(0, 1); lcd.print("Done."); delay(1000); ESP.restart(); } else if (digitalRead(AP_DATA_RESET_PIN) == HIGH) { if (digitalRead(AP_DATA_RESET_PIN) == HIGH) DEBUG_MSG("Reset AP data pressed\n"); last_reset_ap_check = true; } else last_reset_ap_check = false; } void show_time(void) { char dt[21]; if (DateTime.isTimeValid()) { DateTimeParts p = DateTime.getParts(); if (p.getHours() == 0 && p.getMinutes() == 0 && p.getSeconds() == 0) DateTime.forceUpdate(); if ((p.getHours() == 2 || p.getHours() == 3) && p.getMinutes() == 0 && p.getSeconds() == 0) { if (is_wintertime(DateTime.getTime()) == false) add_summertime = 1; else add_summertime = 0; } sprintf(dt, "%02d.%02d.%4d %02d:%02d:%02d", p.getMonthDay(), p.getMonth() + 1, p.getYear(), p.getHours() + add_summertime, p.getMinutes(), p.getSeconds()); DEBUG_MSG("%s", dt); if (add_summertime > 0) DEBUG_MSG(" Summertime\n"); else DEBUG_MSG(" Wintertime\n"); } else sprintf(dt, "--:--:---- --:--:--"); lcd.setCursor(0, 0); lcd.print(dt); digitalWrite(ONBOARD_LED, led_state); led_state = !led_state; } void show_temperature(void) { get_sensor_data(); DEBUG_MSG("Temperature: %02.2f\n", temp[ACT]); lcd.setCursor(0, 1); lcd.print("Temperatur: "); lcd.print(temp[ACT], 1); lcd.write(0); lcd.print("C"); if (millis() > FIRST_MIN_MAX) { lcd.setCursor(0, 2); lcd.print("Min: "); lcd.print(temp[MIN], 1); lcd.print(" Max: "); lcd.print(temp[MAX], 1); } lcd.setCursor(0, 3); lcd.print("LF: "); lcd.print(hum[ACT], 1); lcd.print("%"); lcd.print(" GT: "); lcd.print(heat[ACT], 1); } bool is_wintertime(time_t t) { // Sommerzeit/Winterzeit http://manfred.wilzeck.de/Datum_berechnen.html#Jahreszahl // Tag = 31 – ( 4 + Jahr*5 / 4) MOD 7 ' Datum Tag für Beginn Sommerzeit (Jahr 4-stellig) // Tag = 31 – ( 1 + Jahr*5 / 4) MOD 7 ' Datum Tag für Ende Sommerzeit (Jahr 4-stellig) tmElements_t tm; byte day_of_switch[2]; time_t switch_secs[2]; byte i; day_of_switch[0] = 31 - (4 + year(t) * 5 / 4) % 7; // winter->summer day_of_switch[1] = 31 - (1 + year(t) * 5 / 4) % 7; // summer->winter for (i = 0; i < 2; i++) { tm.Second = 0; if (i == 0) tm.Hour = 2; else tm.Hour = 3; tm.Minute = 0; tm.Day = day_of_switch[i]; if (i == 0) tm.Month = 3; else tm.Month = 10; tm.Year = year(t) - 1970; switch_secs[i] = makeTime(tm); } if (t >= switch_secs[0] && t < switch_secs[1]) return (false); else return (true); } void get_sensor_data(void) { temp[ACT] = constrain(dht.readTemperature(), -40.0, 80.0); hum[ACT] = constrain(dht.readHumidity(), 0.0, 100.0); heat[ACT] = constrain(dht.computeHeatIndex(temp[ACT], hum[ACT], false), -40.0, 80.0); if (minmax_enabled == false && millis() > FIRST_MIN_MAX) { minmax_enabled = true; temp[MIN] = temp[ACT]; temp[MAX] = temp[ACT]; hum[MIN] = hum[ACT]; hum[MAX] = hum[ACT]; heat[MIN] = heat[ACT]; heat[MIN] = heat[ACT]; } if (minmax_enabled == true) { if (temp[ACT] < temp[MIN]) temp[MIN] = temp[ACT]; if (temp[ACT] > temp[MAX]) temp[MAX] = temp[ACT]; if (hum[ACT] < hum[MIN]) hum[MIN] = hum[ACT]; if (hum[ACT] > hum[MAX]) hum[MAX] = hum[ACT]; if (heat[ACT] < heat[MIN]) heat[MIN] = heat[ACT]; if (heat[ACT] > heat[MAX]) heat[MAX] = heat[ACT]; } }