#include #include #include #include // Wifi (Hotspot) const char wifiSSID[] = "FreeWifi"; const char wifiPASS[] = "temppassword"; // ESP8266 (Wifi module, AT firmware) SoftwareSerial wifiSerial(2, 3); // RX = 2, TX = 3 WiFiEspClient client; // LCD Display #define DHT_SENSOR_TYPE DHT_TYPE_11 static const int DHT_SENSOR_PIN = A1; DHT_nonblocking dht_sensor(DHT_SENSxOR_PIN, DHT_SENSOR_TYPE); LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // RS, EN, D4, D5, D6, D7 // Light sensor and LEDs int lightPin = A0; // LDR int dataPin = 4; // DS int latchPin = 5; // ST_CP int clockPin = 6; // SH_CP int leds = 0; // API const float NO_TEMP = -999.0; const unsigned long API_INTERVAL = 600000UL; // 10m const unsigned long RETRY_INTERVAL = 30000UL; // 30s unsigned long lastApiFetch = 0; unsigned long fetchInterval = API_INTERVAL; float outdoorTemp = NO_TEMP; // Connect to hotspot if not connected, then fetch the current temperature float fetchOutdoorTemp() { if (WiFi.status() != WL_CONNECTED) { WiFi.begin(wifiSSID, wifiPASS); if (WiFi.status() != WL_CONNECTED) return NO_TEMP; } client.setTimeout(5000); if (!client.connect("api.open-meteo.com", 80)) return NO_TEMP; client.print(F("GET /v1/forecast?latitude=49.46998&longitude=8.4819¤t=temperature_2m HTTP/1.1\r\n" "Host: api.open-meteo.com\r\n" "Connection: close\r\n" "\r\n")); // Skip ahead to the number in {"current":{..."temperature_2m":12.3}} float t = NO_TEMP; if (client.find("\"current\":") && client.find("\"temperature_2m\":")) { t = client.parseFloat(); } client.stop(); return t; } // Write to LCD display void lcdLine(uint8_t row, const char *text) { lcd.setCursor(0, row); uint8_t i = 0; for (; text[i] != '\0' && i < 16; i++) lcd.write(text[i]); for (; i < 16; i++) lcd.write(' '); } // LEDs for light sensor void updateShiftRegister() { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, leds); digitalWrite(latchPin, HIGH); } // Measure temperature and humidity static bool measure_environment(float *temp, float *hum) { static unsigned long timestamp = millis(); if (millis() - timestamp > 3000ul) { if (dht_sensor.measure(temp, hum) == true) { timestamp = millis(); return true; } } return false; } void setup() { pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); Serial.begin(115200); lcd.begin(16, 2); lcdLine(0, "Connecting WiFi"); lcdLine(1, ""); wifiSerial.begin(9600); WiFi.init(&wifiSerial); if (WiFi.status() == WL_NO_SHIELD) { lcdLine(0, "ESP not found"); delay(2000); } outdoorTemp = fetchOutdoorTemp(); lastApiFetch = millis(); fetchInterval = (outdoorTemp == NO_TEMP) ? RETRY_INTERVAL : API_INTERVAL; lcd.clear(); } void loop() { float indoorTemp; float indoorHum; if (measure_environment(&indoorTemp, &indoorHum) == true) { char tempStr[10]; dtostrf(indoorTemp, 4, 1, tempStr); char line0[20]; snprintf(line0, sizeof(line0), "In: %s C", tempStr); lcdLine(0, line0); } if (millis() - lastApiFetch >= fetchInterval) { float t = fetchOutdoorTemp(); lastApiFetch = millis(); if (t != NO_TEMP) { outdoorTemp = t; fetchInterval = API_INTERVAL; } else { fetchInterval = RETRY_INTERVAL; } } if (outdoorTemp != NO_TEMP) { char outStr[10]; dtostrf(outdoorTemp, 4, 1, outStr); char line1[20]; snprintf(line1, sizeof(line1), "Out: %s C", outStr); lcdLine(1, line1); } else { lcdLine(1, "Out: API Error"); } int reading = analogRead(lightPin); int numLEDSLit = reading / 57; if (numLEDSLit > 8) numLEDSLit = 8; leds = 0; for (int i = 0; i < numLEDSLit; i++) { leds = leds + (1 << i); } updateShiftRegister(); delay(100); }