// Use from 0 to 4. Higher number, more debugging messages and memory usage. #define _WIFIMGR_LOGLEVEL_ 1 #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 34 #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 LiquidCrystal_I2C lcd(LCD_I2C_ADDR, LCD_COL, LCD_ROW); looper sched; RunningMedian samples = RunningMedian(MEDIAN_SAMPLES); float temp_min; float temp_max; float temp; bool led_state; String header; WiFiServer server(80); const uint8_t degree_sign[8] = { B00010, B00101, B00010, B00000, B00000, B00000, B00000, B00000 }; uint8_t add_summertime = 0; bool last_config_check = false; 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")); DEBUG_MSG("Mode Client\n"); 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(NTP_TIMEOUT); while (!DateTime.isTimeValid()) { Serial.println("Failed to get time from server."); DateTime.forceUpdate(); } if (is_wintertime(DateTime.getTime()) == false) add_summertime = 1; else add_summertime = 0; // create a degree sign lcd.createChar(0, (uint8_t*)degree_sign); server.begin(); sched.addJob(show_temperature, KRATE_TEMP); sched.addJob(show_time, KRATE_TIME); sched.addJob(start_config_portal, KRATE_RESET_AP_DATA); temp_min = get_temp_sensor_data(); temp_max = temp_min; temp = temp_min; lcd.clear(); show_time(); show_temperature(); } void loop() { sched.scheduler(); WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, Serial.println("New Client."); // 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("\n"); client.println("\n"); client.println("\n"); client.println("\n"); client.println("
\n"); client.println("

Temperatur Kirche

\n"); client.print("

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

\n"); client.print("

Minimum: "); client.print(temp_min); client.println(" °C

\n"); client.print("

Maximum: "); client.print(temp_max); client.println(" °C

\n"); client.println("
\n"); client.println("\n"); 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(); Serial.println("Client disconnected."); Serial.println(""); } } void start_config_portal(void) { if (digitalRead(AP_DATA_RESET_PIN) == HIGH && last_config_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_config_check = true; } else last_config_check = false; } void show_time(void) { DateTimeParts p = DateTime.getParts(); char dt[21]; 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()); Serial.print(dt); if (add_summertime > 0) Serial.println(" Summertime"); else Serial.println(" Wintertime"); lcd.setCursor(0, 0); lcd.print(dt); digitalWrite(ONBOARD_LED, led_state); led_state = !led_state; } void show_temperature(void) { float new_temp = get_temp_sensor_data(); DEBUG_MSG("Temperature: %02.2f\n", new_temp); if (new_temp > temp) { if (new_temp - temp > 1.0) temp = temp + 1.0; else temp = new_temp; } else if (new_temp < temp) { if (new_temp - temp < -1.0) temp = temp - 1.0; else temp = new_temp; } samples.add(temp); if (samples.getLowest() < temp_min) temp_min = samples.getLowest(); if (samples.getHighest() > temp_max) temp_max = samples.getHighest(); lcd.setCursor(0, 1); lcd.print("Temperatur: "); lcd.print(temp); lcd.write(0); lcd.print("C"); lcd.setCursor(0, 2); lcd.print("Minimum: "); lcd.print(temp_min); lcd.write(0); lcd.print("C"); lcd.setCursor(0, 3); lcd.print("Maximum: "); lcd.print(temp_max); lcd.write(0); lcd.print("C"); } 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); } float get_temp_sensor_data(void) { float t = constrain((analogRead(TEMP_SENS_PIN) / 2048.0) * 330.0, 0.0, 50.0); return (t); }