ESP32- DHT22 - Nextion Display Weather Station
A very cool weather station with the help of ESP32, sensor DHT22, Nextion Display and measurements from openweathermap.org!
Components and supplies
Resistor 10k ohm
DHT22 Temperature Sensor
Nextion NX4024T032 - Generic 3.2" HMI TFT Intelligent LCD Touch Display Module
Flash Memory Card, SD Card
ESP32
USB-A to Micro-USB Cable
Tools and machines
Servo Motor, Premium Male/Male Jumper Wires
Premium Female/Male Extension Jumper Wires, 40 x 6" (150mm)
Apps and platforms
Arduino IDE
Windows 10
Project description
Code
Project_code
arduino
1/*************************************************************************************************************************************** 2 WEATHER STATION WITH ESP32 - DHT 22 - NEXTION DISPLAY - HTTP SERVER 3DIY ESP32 Projects 4****************************************************************************************************************************************/ 5#include <WiFi.h> 6#include <WebServer.h> 7#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson 8#include "DHTesp.h" 9#include "time.h" 10 11#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 12 13/*Put your SSID & Password*/ 14const char* ssid = "yourSSID"; // Enter SSID here 15const char* password = "PASSWORD"; //Enter Password here 16String CityID = "cityID"; //Enter your City ID from api.weathermap.org 17String APIKEY = "youapikey"; // your api_key 18#define LED_PIN 2 19WebServer server(80); 20 21// DHT Sensor 22uint8_t DHTPin = 4; 23 24// Initialize DHT sensor. 25DHTesp dht; 26 27 28int days,DST=0; 29const char* ntpServer = "europe.pool.ntp.org"; 30const long gmtOffset_sec = 7200; //GMT+1 for Greece, Default gmtOffset_sec=3600 for Europe GMT 31const int daylightOffset_sec = 3600; 32 33 34 35String final_time_string; 36String final_time_string2; 37String final_date_string; 38String final_date_string2; 39String final_date_string3; 40 41 42float temperaturein = 0; 43float Temperature = 0; 44float humidityin = 0; 45float Humidity = 0; 46float backuptemp=0; // backup temperature in case of nan error 47float backuphumi=0; // backup humidity in case of nan error 48 int weatherID = 0; 49float hum = 0; 50float tempout=0; 51 52char* servername ="api.openweathermap.org"; // remote server we will connect to 53String result; 54String result2; 55int iterations = 1800; 56String weatherDescription =""; 57String weatherLocation = ""; 58char last_letter; 59char last_letter2; 60 61void setup() { 62 63 pinMode(LED_PIN, OUTPUT); 64 Serial.begin(9600); 65 66 dht.setup(DHTPin, DHTesp::DHT22); 67 68 Serial.println("Connecting to "); 69 Serial.println(ssid); 70 71 //connect to your local wi-fi network 72 WiFi.begin(ssid, password); 73 74 //check wi-fi is connected to wi-fi network 75 while (WiFi.status() != WL_CONNECTED) 76 { 77 delay(1000); 78 Serial.print("."); 79 } 80 Serial.println(""); 81 Serial.println("WiFi connected..!"); 82 Serial.print("Got IP: "); 83 Serial.println(WiFi.localIP()); 84 85 server.on("/", handle_OnConnect); 86 server.onNotFound(handle_NotFound); 87 88 server.begin(); //start server 89 Serial.println("HTTP server started"); 90 91 configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); //setup time 92 printLocalTime(); //print time 93} 94 95 96 97void loop() 98{ 99 server.handleClient(); 100 printLocalTime(); 101 printWeatherIcon(weatherID); 102 delay(2000); 103 104 if(iterations == 1800)//We check for changes in weather every half an hour 105 { 106 getWeatherData(); 107 getWeatheropenweather(); 108 109 printWeatherIcon(weatherID); 110 iterations = 0; 111 } 112 113 sendopenweatherTemperatureToNextion(); //send outside temperature from openweather to nextion display 114 sendopenweatherHumidityToNextion(); //send outside humidity from openweather to nextion display 115 printfinaldate(); //send date to nextion diplay 116 printfinaltime(); //send time to nextion diplay 117 delay(20000); 118 getTemperature(); //measure inside temperature every 20 seconds 119 sendTemperatureToNextion(); //send inside temperature from openweather to nextion display 120 delay(5000); //small delay between measurements 121 getHumidity(); //measure inside humidity every 25 seconds 122 sendHumidityToNextion(); //send inside humidity from openweather to nextion display 123 iterations++; 124} 125 126 127void printLocalTime() 128{ 129 struct tm timeinfo; 130 if(!getLocalTime(&timeinfo)) 131 { 132 Serial.println("Failed to obtain time"); 133 return; 134 } 135 Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 136 137 138 final_time_string=timeinfo.tm_hour; 139 final_time_string2=timeinfo.tm_min; 140 141 final_date_string=timeinfo.tm_mday; 142 final_date_string2=timeinfo.tm_mon+1; 143 final_date_string3=timeinfo.tm_year+1900; 144 145 int length = final_date_string3.length(); 146 final_date_string3[length-1] = last_letter; // we need to get the last two numbers of 2019 because of lack of space 147 final_date_string3[length-2] = last_letter2; 148 Serial.println(last_letter); 149 Serial.println(last_letter2); 150 Serial.println(final_date_string3[length-1]); 151 Serial.println(final_date_string3[length-2]); 152 153} 154 155 156float getTemperature() 157{ 158 temperaturein = dht.getTemperature(); 159 if (isnan(temperaturein)) 160 { 161 digitalWrite(DHTPin, LOW); 162 delay(1000); 163 digitalWrite(DHTPin, HIGH); 164 delay(1000); 165 } 166 if (!isnan(temperaturein)) //save last value and get a backup in case of a nan error 167 { 168 backuptemp=temperaturein; 169 } 170} 171 172float getHumidity() 173{ 174 humidityin = dht.getHumidity(); 175 if (isnan(humidityin)) //save last value and get a backup in case of a nan error 176 { 177 digitalWrite(DHTPin, LOW); 178 delay(1000); 179 digitalWrite(DHTPin, HIGH); 180 delay(1000); 181 } 182 if (!isnan(humidityin)) //save last value and get a backup in case of a nan error 183 { 184 backuphumi=humidityin; 185 } 186} 187 188//get forecast 189void getWeatherData() //client function to send/receive GET request data. 190{ 191 String result =""; 192 WiFiClient client; 193 const int httpPort = 80; 194 if (!client.connect(servername, httpPort)) { 195 return; 196 } 197 // We now create a URI for the request 198 String url = "/data/2.5/forecast?id="+CityID+"&units=metric&cnt=1&APPID="+APIKEY; 199 200 // This will send the request to the server 201 client.print(String("GET ") + url + " HTTP/1.1\ \ 202" + 203 "Host: " + servername + "\ \ 204" + 205 "Connection: close\ \ 206\ \ 207"); 208 209 unsigned long timeout = millis(); 210 while (client.available() == 0) 211 { 212 if (millis() - timeout > 5000) 213 { 214 client.stop(); 215 return; 216 } 217 } 218 219 // Read all the lines of the reply from server 220 while(client.available()) 221 { 222 result = client.readStringUntil('\r'); 223 } 224 225 result.replace('[', ' '); 226 result.replace(']', ' '); 227 228 char jsonArray [result.length()+1]; 229 result.toCharArray(jsonArray,sizeof(jsonArray)); 230 jsonArray[result.length() + 1] = '\\0'; 231 232 StaticJsonBuffer<1024> json_buf; 233 JsonObject &root = json_buf.parseObject(jsonArray); 234 if (!root.success()) 235 { 236 Serial.println("parseObject() failed"); 237 } 238 239 String location = root["city"]["name"]; 240 String temperature = root["list"]["main"]["temp"]; 241 String weather = root["list"]["weather"]["main"]; 242 String description = root["list"]["weather"]["description"]; 243 String idString = root["list"]["weather"]["id"]; 244 String timeS = root["list"]["dt_txt"]; 245 246 weatherID = idString.toInt(); 247 Serial.print("\ 248WeatherID: "); 249 Serial.print(weatherID); 250 endNextionCommand(); //We need that in order the nextion to recognise the first command after the serial print 251} 252 253 254//get current weather 255void getWeatheropenweather() 256{ 257 String result2 =""; 258 WiFiClient client2; 259 const int httpPort2 = 80; 260 if (!client2.connect(servername, httpPort2)) 261 { 262 return; 263 } 264 265 String url2 = "/data/2.5/weather?id="+CityID+"&units=metric"+"&APPID="+APIKEY; 266 client2.print(String("GET ") + url2 + " HTTP/1.1\ \ 267" + 268 "Host: " + servername + "\ \ 269" + 270 "Connection: close\ \ 271\ \ 272"); 273 unsigned long timeout2 = millis(); 274 while (client2.available() == 0) 275 { 276 if (millis() - timeout2 > 5000) 277 { 278 client2.stop(); 279 return; 280 } 281 } 282 283 // Read all the lines of the reply from server 284 while(client2.available()) 285 { 286 result2 = client2.readStringUntil('\r'); 287 } 288 289 result2.replace('[', ' '); 290 result2.replace(']', ' '); 291 292 char jsonArray2 [result2.length()+1]; 293 result2.toCharArray(jsonArray2,sizeof(jsonArray2)); 294 jsonArray2[result2.length() + 1] = '\\0'; 295 StaticJsonBuffer<1024> json_buf2; 296 JsonObject &root2 = json_buf2.parseObject(jsonArray2); 297 298 String humi = root2["main"]["humidity"]; // Extract local humidity now 299 hum = humi.toInt(); 300 Serial.print("\ 301humi: "); 302 Serial.print(hum); 303 304 String temp = root2["main"]["temp"]; // Extract local temp now 305 tempout = temp.toInt(); 306 Serial.print("\ empout: "); 307 Serial.print(tempout); 308 309 endNextionCommand(); 310} 311 312void showConnectingIcon() 313{ 314 Serial.println(); 315 String command = "weatherIcon.pic=3"; 316 Serial.print(command); 317 endNextionCommand(); 318} 319 320void showconnectionweatherlater1() 321{ 322 Serial.println(); 323 String command = "weatherpic1.pic=3"; 324 Serial.print(command); 325 endNextionCommand(); 326} 327 328void printfinaldate() 329{ 330 String command2 = "date.txt=\\""+String(final_date_string+"/"+final_date_string2+"/"+"19")+"\\""; 331 Serial.print(command2); 332 endNextionCommand(); 333} 334 335void printfinaltime() 336{ 337 String command = "time.txt=\\""+String(final_time_string+":"+final_time_string2)+"\\""; 338 Serial.print(command); 339 endNextionCommand(); 340} 341 342void sendopenweatherTemperatureToNextion() 343{ 344 String command = "temperatureout.txt=\\""+String(tempout,1)+"\\""; 345 Serial.print(command); 346 endNextionCommand(); 347} 348 349void sendopenweatherHumidityToNextion() 350{ 351 String command = "humidityout.txt=\\""+String(hum,1)+"\\""; 352 Serial.print(command); 353 endNextionCommand(); 354} 355 356void sendHumidityToNextion() 357{ 358 if (!isnan(humidityin)) 359 { 360 String command = "humidity.txt=\\""+String(humidityin)+"\\""; 361 Serial.print(command); 362 endNextionCommand(); 363 } 364 if (isnan(humidityin)) 365 { 366 String command = "humidity.txt=\\""+String(backuphumi)+"\\""; 367 Serial.print(command); 368 endNextionCommand(); 369 } 370} 371 372void sendTemperatureToNextion() 373{ 374 if (!isnan(temperaturein)) 375 { 376 String command = "temperaturein.txt=\\""+String(temperaturein,1)+"\\""; 377 Serial.print(command); 378 endNextionCommand(); 379 } 380 if (isnan(temperaturein)) 381 { 382 String command = "temperaturein.txt=\\""+String(backuptemp,1)+"\\""; 383 Serial.print(command); 384 endNextionCommand(); 385 } 386} 387 388void endNextionCommand() 389{ 390 Serial.write(0xff); 391 Serial.write(0xff); 392 Serial.write(0xff); 393} 394 395void printWeatherIcon(int id) 396{ 397 switch(id) 398 { 399 case 800: drawClearWeather(); break; 400 case 801: drawFewClouds(); break; 401 case 802: drawFewClouds(); break; 402 case 803: drawCloud(); break; 403 case 804: drawCloud(); break; 404 405 case 200: drawThunderstorm(); break; 406 case 201: drawThunderstorm(); break; 407 case 202: drawThunderstorm(); break; 408 case 210: drawThunderstorm(); break; 409 case 211: drawThunderstorm(); break; 410 case 212: drawThunderstorm(); break; 411 case 221: drawThunderstorm(); break; 412 case 230: drawThunderstorm(); break; 413 case 231: drawThunderstorm(); break; 414 case 232: drawThunderstorm(); break; 415 416 case 300: drawLightRain(); break; 417 case 301: drawLightRain(); break; 418 case 302: drawLightRain(); break; 419 case 310: drawLightRain(); break; 420 case 311: drawLightRain(); break; 421 case 312: drawLightRain(); break; 422 case 313: drawLightRain(); break; 423 case 314: drawLightRain(); break; 424 case 321: drawLightRain(); break; 425 426 case 500: drawLightRainWithSunOrMoon(); break; 427 case 501: drawLightRainWithSunOrMoon(); break; 428 case 502: drawLightRainWithSunOrMoon(); break; 429 case 503: drawLightRainWithSunOrMoon(); break; 430 case 504: drawLightRainWithSunOrMoon(); break; 431 case 511: drawLightRain(); break; 432 case 520: drawModerateRain(); break; 433 case 521: drawModerateRain(); break; 434 case 522: drawHeavyRain(); break; 435 case 531: drawHeavyRain(); break; 436 437 case 600: drawLightSnowfall(); break; 438 case 601: drawModerateSnowfall(); break; 439 case 602: drawHeavySnowfall(); break; 440 case 611: drawLightSnowfall(); break; 441 case 612: drawLightSnowfall(); break; 442 case 615: drawLightSnowfall(); break; 443 case 616: drawLightSnowfall(); break; 444 case 620: drawLightSnowfall(); break; 445 case 621: drawModerateSnowfall(); break; 446 case 622: drawHeavySnowfall(); break; 447 448 case 701: drawFog(); break; 449 case 711: drawFog(); break; 450 case 721: drawFog(); break; 451 case 731: drawFog(); break; 452 case 741: drawFog(); break; 453 case 751: drawFog(); break; 454 case 761: drawFog(); break; 455 case 762: drawFog(); break; 456 case 771: drawFog(); break; 457 case 781: drawFog(); break; 458 459 default:break; 460 } 461} 462 463 464 465void drawFog() 466{ 467 String command = "weatherIcon.pic=13"; 468 Serial.print(command); 469 endNextionCommand(); 470} 471 472void drawHeavySnowfall() 473{ 474 String command = "weatherIcon.pic=8"; 475 Serial.print(command); 476 endNextionCommand(); 477} 478 479void drawModerateSnowfall() 480{ 481 String command = "weatherIcon.pic=8"; 482 Serial.print(command); 483 endNextionCommand(); 484} 485 486void drawLightSnowfall() 487{ 488 String command = "weatherIcon.pic=11"; 489 Serial.print(command); 490 endNextionCommand(); 491} 492 493void drawHeavyRain() 494{ 495 String command = "weatherIcon.pic=10"; 496 Serial.print(command); 497 endNextionCommand(); 498} 499 500void drawModerateRain() 501{ 502 String command = "weatherIcon.pic=6"; 503 Serial.print(command); 504 endNextionCommand(); 505} 506 507void drawLightRain() 508{ 509 String command = "weatherIcon.pic=6"; 510 Serial.print(command); 511 endNextionCommand(); 512} 513 514void drawLightRainWithSunOrMoon() 515{ 516 String command = "weatherIcon.pic=7"; 517 Serial.print(command); 518 endNextionCommand(); 519} 520void drawThunderstorm() 521{ 522 String command = "weatherIcon.pic=3"; 523 Serial.print(command); 524 endNextionCommand(); 525} 526 527void drawClearWeather() 528{ 529 String command = "weatherIcon.pic=4"; 530 Serial.print(command); 531 Serial.write(0xff); 532 Serial.write(0xff); 533 Serial.write(0xff); 534} 535 536void drawCloud() 537{ 538 String command = "weatherIcon.pic=9"; 539 Serial.print(command); 540 endNextionCommand(); 541} 542 543void drawFewClouds() 544{ 545 String command = "weatherIcon.pic=5"; 546 Serial.print(command); 547 endNextionCommand(); 548} 549 550 551 552// HTTP server handling 553 554void handle_OnConnect() { 555 556 Temperature = dht.getTemperature(); // Gets the values of the temperature 557 Humidity = dht.getHumidity(); // Gets the values of the humidity 558 559 if (!isnan(temperaturein)) 560 { 561 server.send(200, "text/html", SendHTML(temperaturein,temperaturein,humidityin)); 562 Serial.print("Temperature:"); 563 Serial.println(dht.getTemperature()); 564 } 565 if (!isnan(temperaturein)) 566 { 567 server.send(200, "text/html", SendHTML(backuptemp,backuptemp,backuphumi)); 568 Serial.print("Temperature:"); 569 Serial.println(dht.getTemperature()); 570 } 571} 572 573void handle_NotFound(){ 574 server.send(404, "text/plain", "Not found"); 575} 576 577String SendHTML(float TempCstat,float TempFstat,float Humiditystat){ 578 String ptr = "<!DOCTYPE html> <html>\ 579"; 580 ptr +="<head><meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0, user-scalable=no\\">\ 581"; 582 ptr +="<link href=\\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\\" rel=\\"stylesheet\\">\ 583"; 584 ptr +="<title>ESP32 Weather Report</title>\ 585"; 586 ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\ 587"; 588 ptr +="body{margin-top: 50px;}\ 589"; 590 ptr +="h1 {margin: 50px auto 30px;}\ 591"; 592 ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\ 593"; 594 ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\ 595"; 596 ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\ 597"; 598 ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\ 599"; 600 ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\ 601"; 602 ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\ 603"; 604 ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\ 605"; 606 ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\ 607"; 608 ptr +=".data{padding: 10px;}\ 609"; 610 ptr +="</style>\ 611"; 612 ptr +="</head>\ 613"; 614 ptr +="<body>\ 615"; 616 617 ptr +="<div id=\\"webpage\\">\ 618"; 619 620 ptr +="<h1>ESP32 Weather Report</h1>\ 621"; 622 ptr +="<div class=\\"data\\">\ 623"; 624 ptr +="<div class=\\"side-by-side temperature-icon\\">\ 625"; 626 ptr +="<svg version=\\"1.1\\" id=\\"Layer_1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" x=\\"0px\\" y=\\"0px\\"\ 627"; 628 ptr +="width=\\"9.915px\\" height=\\"22px\\" viewBox=\\"0 0 9.915 22\\" enable-background=\\"new 0 0 9.915 22\\" xml:space=\\"preserve\\">\ 629"; 630 ptr +="<path fill=\\"#FFFFFF\\" d=\\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\ 631"; 632 ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\ 633"; 634 ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\ 635"; 636 ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\ 637"; 638 ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\\"/>\ 639"; 640 ptr +="</svg>\ 641"; 642 ptr +="</div>\ 643"; 644 ptr +="<div class=\\"side-by-side temperature-text\\">Temperature</div>\ 645"; 646 ptr +="<div class=\\"side-by-side temperature\\">"; 647 ptr +=(float)TempCstat; 648 ptr +="<span class=\\"superscript\\">C</span></div>\ 649"; 650 ptr +="</div>\ 651"; 652 ptr +="<div class=\\"data\\">\ 653"; 654 ptr +="<div class=\\"side-by-side humidity-icon\\">\ 655"; 656 ptr +="<svg version=\\"1.1\\" id=\\"Layer_2\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" x=\\"0px\\" y=\\"0px\\"\ 657\\"; width=\\"12px\\" height=\\"17.955px\\" viewBox=\\"0 0 13 17.955\\" enable-background=\\"new 0 0 13 17.955\\" xml:space=\\"preserve\\">\ 658"; 659 ptr +="<path fill=\\"#FFFFFF\\" d=\\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\ 660"; 661 ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\\"></path>\ 662"; 663 ptr +="</svg>\ 664"; 665 ptr +="</div>\ 666"; 667 ptr +="<div class=\\"side-by-side humidity-text\\">Humidity</div>\ 668"; 669 ptr +="<div class=\\"side-by-side humidity\\">"; 670 ptr +=(int)Humiditystat; 671 ptr +="<span class=\\"superscript\\">%</span></div>\ 672"; 673 ptr +="</div>\ 674"; 675 676 ptr +="</div>\ 677"; 678 ptr +="</body>\ 679"; 680 ptr +="</html>\ 681"; 682 return ptr; 683} 684
Project_code
arduino
1/*************************************************************************************************************************************** 2 3 WEATHER STATION WITH ESP32 - DHT 22 - NEXTION DISPLAY - HTTP 4 SERVER 5DIY ESP32 Projects 6****************************************************************************************************************************************/ 7#include 8 <WiFi.h> 9#include <WebServer.h> 10#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson 11#include 12 "DHTesp.h" 13#include "time.h" 14 15#define DHTTYPE DHT22 // DHT 22 (AM2302), 16 AM2321 17 18/*Put your SSID & Password*/ 19const char* ssid = "yourSSID"; // 20 Enter SSID here 21const char* password = "PASSWORD"; //Enter Password here 22String 23 CityID = "cityID"; //Enter your City ID from api.weathermap.org 24String APIKEY 25 = "youapikey"; // your api_key 26#define LED_PIN 2 27WebServer server(80); 28 29// 30 DHT Sensor 31uint8_t DHTPin = 4; 32 33// Initialize DHT sensor. 34 35DHTesp dht; 36 37 38int days,DST=0; 39const char* ntpServer 40 = "europe.pool.ntp.org"; 41const long gmtOffset_sec = 7200; //GMT+1 for Greece, 42 Default gmtOffset_sec=3600 for Europe GMT 43const int daylightOffset_sec = 3600; 44 45 46 47String 48 final_time_string; 49String final_time_string2; 50String final_date_string; 51String 52 final_date_string2; 53String final_date_string3; 54 55 56float temperaturein 57 = 0; 58float Temperature = 0; 59float humidityin = 0; 60float Humidity = 0; 61float 62 backuptemp=0; // backup temperature in case of nan error 63float backuphumi=0; 64 // backup humidity in case of nan error 65 int weatherID = 0; 66float 67 hum = 0; 68float tempout=0; 69 70char* servername ="api.openweathermap.org"; 71 // remote server we will connect to 72String result; 73String result2; 74int 75 iterations = 1800; 76String weatherDescription =""; 77String weatherLocation 78 = ""; 79char last_letter; 80char last_letter2; 81 82void setup() { 83 84 85 pinMode(LED_PIN, OUTPUT); 86 Serial.begin(9600); 87 88 dht.setup(DHTPin, 89 DHTesp::DHT22); 90 91 Serial.println("Connecting to "); 92 Serial.println(ssid); 93 94 95 //connect to your local wi-fi network 96 WiFi.begin(ssid, password); 97 98 99 //check wi-fi is connected to wi-fi network 100 while (WiFi.status() != WL_CONNECTED) 101 102 { 103 delay(1000); 104 Serial.print("."); 105 } 106 Serial.println(""); 107 108 Serial.println("WiFi connected..!"); 109 Serial.print("Got IP: "); 110 111 Serial.println(WiFi.localIP()); 112 113 server.on("/", handle_OnConnect); 114 115 server.onNotFound(handle_NotFound); 116 117 server.begin(); //start server 118 119 Serial.println("HTTP server started"); 120 121 configTime(gmtOffset_sec, daylightOffset_sec, 122 ntpServer); //setup time 123 printLocalTime(); //print time 124} 125 126 127 128void 129 loop() 130{ 131 server.handleClient(); 132 printLocalTime(); 133 printWeatherIcon(weatherID); 134 135 delay(2000); 136 137 if(iterations == 1800)//We check for changes in weather 138 every half an hour 139 { 140 getWeatherData(); 141 getWeatheropenweather(); 142 143 144 printWeatherIcon(weatherID); 145 iterations = 0; 146 147 } 148 149 sendopenweatherTemperatureToNextion(); //send outside temperature 150 from openweather to nextion display 151 sendopenweatherHumidityToNextion(); //send 152 outside humidity from openweather to nextion display 153 printfinaldate(); //send 154 date to nextion diplay 155 printfinaltime(); //send time 156 to nextion diplay 157 delay(20000); 158 getTemperature(); //measure 159 inside temperature every 20 seconds 160 sendTemperatureToNextion(); //send 161 inside temperature from openweather to nextion display 162 delay(5000); //small 163 delay between measurements 164 getHumidity(); //measure 165 inside humidity every 25 seconds 166 sendHumidityToNextion(); //send 167 inside humidity from openweather to nextion display 168 iterations++; 169} 170 171 172void 173 printLocalTime() 174{ 175 struct tm timeinfo; 176 if(!getLocalTime(&timeinfo)) 177 178 { 179 Serial.println("Failed to obtain time"); 180 return; 181 } 182 183 Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 184 185 186 final_time_string=timeinfo.tm_hour; 187 188 final_time_string2=timeinfo.tm_min; 189 190 final_date_string=timeinfo.tm_mday; 191 192 final_date_string2=timeinfo.tm_mon+1; 193 final_date_string3=timeinfo.tm_year+1900; 194 195 196 int length = final_date_string3.length(); 197 final_date_string3[length-1] = 198 last_letter; // we need to get the last two numbers of 2019 because of lack of 199 space 200 final_date_string3[length-2] = last_letter2; 201 Serial.println(last_letter); 202 203 Serial.println(last_letter2); 204 Serial.println(final_date_string3[length-1]); 205 206 Serial.println(final_date_string3[length-2]); 207 208} 209 210 211float getTemperature() 212{ 213 214 temperaturein = dht.getTemperature(); 215 if (isnan(temperaturein)) 216 { 217 218 digitalWrite(DHTPin, LOW); 219 delay(1000); 220 digitalWrite(DHTPin, 221 HIGH); 222 delay(1000); 223 } 224 if (!isnan(temperaturein)) //save last value 225 and get a backup in case of a nan error 226 { 227 backuptemp=temperaturein; 228 229 } 230} 231 232float getHumidity() 233{ 234 humidityin = dht.getHumidity(); 235 236 if (isnan(humidityin)) //save last value and get a backup in case of a nan error 237 238 { 239 digitalWrite(DHTPin, LOW); 240 delay(1000); 241 digitalWrite(DHTPin, 242 HIGH); 243 delay(1000); 244 } 245 if (!isnan(humidityin)) //save last value 246 and get a backup in case of a nan error 247 { 248 backuphumi=humidityin; 249 250 } 251} 252 253//get forecast 254void getWeatherData() //client function to send/receive 255 GET request data. 256{ 257 String result =""; 258 WiFiClient client; 259 const 260 int httpPort = 80; 261 if (!client.connect(servername, httpPort)) { 262 return; 263 264 } 265 // We now create a URI for the request 266 String url = "/data/2.5/forecast?id="+CityID+"&units=metric&cnt=1&APPID="+APIKEY; 267 268 269 // This will send the request to the server 270 client.print(String("GET 271 ") + url + " HTTP/1.1\ \ 272" + 273 "Host: " + servername + 274 "\ \ 275" + 276 "Connection: close\ \ 277\ \ 278"); 279 280 281 unsigned long timeout = millis(); 282 while (client.available() == 0) 283 284 { 285 if (millis() - timeout > 5000) 286 { 287 client.stop(); 288 289 return; 290 } 291 } 292 293 // Read all the lines of the 294 reply from server 295 while(client.available()) 296 { 297 result = 298 client.readStringUntil('\ '); 299 } 300 301 result.replace('[', ' '); 302 303 result.replace(']', ' '); 304 305 char jsonArray [result.length()+1]; 306 307 result.toCharArray(jsonArray,sizeof(jsonArray)); 308 jsonArray[result.length() 309 + 1] = '\\0'; 310 311 StaticJsonBuffer<1024> json_buf; 312 JsonObject 313 &root = json_buf.parseObject(jsonArray); 314 if (!root.success()) 315 { 316 317 Serial.println("parseObject() failed"); 318 } 319 320 String location 321 = root["city"]["name"]; 322 String temperature = root["list"]["main"]["temp"]; 323 324 String weather = root["list"]["weather"]["main"]; 325 String description 326 = root["list"]["weather"]["description"]; 327 String idString = root["list"]["weather"]["id"]; 328 329 String timeS = root["list"]["dt_txt"]; 330 331 weatherID = idString.toInt(); 332 333 Serial.print("\ 334WeatherID: "); 335 Serial.print(weatherID); 336 endNextionCommand(); 337 //We need that in order the nextion to recognise the first command after the serial 338 print 339} 340 341 342//get current weather 343void getWeatheropenweather() 344{ 345 346 String result2 =""; 347 WiFiClient client2; 348 const int httpPort2 = 80; 349 350 if (!client2.connect(servername, httpPort2)) 351 { 352 return; 353 } 354 355 356 String url2 = "/data/2.5/weather?id="+CityID+"&units=metric"+"&APPID="+APIKEY; 357 358 client2.print(String("GET ") + url2 + " HTTP/1.1\ \ 359" + 360 "Host: 361 " + servername + "\ \ 362" + 363 "Connection: close\ \ 364\ \ 365"); 366 367 unsigned long timeout2 = millis(); 368 while (client2.available() == 0) 369 370 { 371 if (millis() - timeout2 > 5000) 372 { 373 client2.stop(); 374 375 return; 376 } 377 } 378 379 // Read all the lines of the reply 380 from server 381 while(client2.available()) 382 { 383 result2 = client2.readStringUntil('\ '); 384 385 } 386 387 result2.replace('[', ' '); 388 result2.replace(']', ' '); 389 390 391 char jsonArray2 [result2.length()+1]; 392 result2.toCharArray(jsonArray2,sizeof(jsonArray2)); 393 394 jsonArray2[result2.length() + 1] = '\\0'; 395 StaticJsonBuffer<1024> json_buf2; 396 397 JsonObject &root2 = json_buf2.parseObject(jsonArray2); 398 399 String 400 humi = root2["main"]["humidity"]; // Extract local humidity now 401 hum 402 = humi.toInt(); 403 Serial.print("\ 404humi: "); 405 Serial.print(hum); 406 407 408 String temp = root2["main"]["temp"]; // Extract local temp now 409 410 tempout = temp.toInt(); 411 Serial.print("\ empout: "); 412 Serial.print(tempout); 413 414 415 endNextionCommand(); 416} 417 418void showConnectingIcon() 419{ 420 Serial.println(); 421 422 String command = "weatherIcon.pic=3"; 423 Serial.print(command); 424 endNextionCommand(); 425} 426 427void 428 showconnectionweatherlater1() 429{ 430 Serial.println(); 431 String command = 432 "weatherpic1.pic=3"; 433 Serial.print(command); 434 endNextionCommand(); 435} 436 437void 438 printfinaldate() 439{ 440 String command2 = "date.txt=\\""+String(final_date_string+"/"+final_date_string2+"/"+"19")+"\\""; 441 442 Serial.print(command2); 443 endNextionCommand(); 444} 445 446void printfinaltime() 447{ 448 449 String command = "time.txt=\\""+String(final_time_string+":"+final_time_string2)+"\\""; 450 451 Serial.print(command); 452 endNextionCommand(); 453} 454 455void sendopenweatherTemperatureToNextion() 456{ 457 458 String command = "temperatureout.txt=\\""+String(tempout,1)+"\\""; 459 Serial.print(command); 460 461 endNextionCommand(); 462} 463 464void sendopenweatherHumidityToNextion() 465{ 466 467 String command = "humidityout.txt=\\""+String(hum,1)+"\\""; 468 Serial.print(command); 469 470 endNextionCommand(); 471} 472 473void sendHumidityToNextion() 474{ 475 if (!isnan(humidityin)) 476 477 { 478 String command = "humidity.txt=\\""+String(humidityin)+"\\""; 479 480 Serial.print(command); 481 endNextionCommand(); 482 } 483 if (isnan(humidityin)) 484 485 { 486 String command = "humidity.txt=\\""+String(backuphumi)+"\\""; 487 488 Serial.print(command); 489 endNextionCommand(); 490 } 491} 492 493void 494 sendTemperatureToNextion() 495{ 496 if (!isnan(temperaturein)) 497 { 498 String 499 command = "temperaturein.txt=\\""+String(temperaturein,1)+"\\""; 500 Serial.print(command); 501 502 endNextionCommand(); 503 } 504 if (isnan(temperaturein)) 505 { 506 String 507 command = "temperaturein.txt=\\""+String(backuptemp,1)+"\\""; 508 Serial.print(command); 509 510 endNextionCommand(); 511 } 512} 513 514void endNextionCommand() 515{ 516 517 Serial.write(0xff); 518 Serial.write(0xff); 519 Serial.write(0xff); 520} 521 522void 523 printWeatherIcon(int id) 524{ 525 switch(id) 526 { 527 case 800: drawClearWeather(); 528 break; 529 case 801: drawFewClouds(); break; 530 case 802: drawFewClouds(); break; 531 532 case 803: drawCloud(); break; 533 case 804: drawCloud(); break; 534 535 case 536 200: drawThunderstorm(); break; 537 case 201: drawThunderstorm(); break; 538 case 539 202: drawThunderstorm(); break; 540 case 210: drawThunderstorm(); break; 541 case 542 211: drawThunderstorm(); break; 543 case 212: drawThunderstorm(); break; 544 case 545 221: drawThunderstorm(); break; 546 case 230: drawThunderstorm(); break; 547 case 548 231: drawThunderstorm(); break; 549 case 232: drawThunderstorm(); break; 550 551 552 case 300: drawLightRain(); break; 553 case 301: drawLightRain(); break; 554 case 555 302: drawLightRain(); break; 556 case 310: drawLightRain(); break; 557 case 311: 558 drawLightRain(); break; 559 case 312: drawLightRain(); break; 560 case 313: drawLightRain(); 561 break; 562 case 314: drawLightRain(); break; 563 case 321: drawLightRain(); break; 564 565 566 case 500: drawLightRainWithSunOrMoon(); break; 567 case 501: drawLightRainWithSunOrMoon(); 568 break; 569 case 502: drawLightRainWithSunOrMoon(); break; 570 case 503: drawLightRainWithSunOrMoon(); 571 break; 572 case 504: drawLightRainWithSunOrMoon(); break; 573 case 511: drawLightRain(); 574 break; 575 case 520: drawModerateRain(); break; 576 case 521: drawModerateRain(); 577 break; 578 case 522: drawHeavyRain(); break; 579 case 531: drawHeavyRain(); break; 580 581 582 case 600: drawLightSnowfall(); break; 583 case 601: drawModerateSnowfall(); break; 584 585 case 602: drawHeavySnowfall(); break; 586 case 611: drawLightSnowfall(); break; 587 588 case 612: drawLightSnowfall(); break; 589 case 615: drawLightSnowfall(); break; 590 591 case 616: drawLightSnowfall(); break; 592 case 620: drawLightSnowfall(); break; 593 594 case 621: drawModerateSnowfall(); break; 595 case 622: drawHeavySnowfall(); break; 596 597 598 case 701: drawFog(); break; 599 case 711: drawFog(); break; 600 case 721: drawFog(); 601 break; 602 case 731: drawFog(); break; 603 case 741: drawFog(); break; 604 case 605 751: drawFog(); break; 606 case 761: drawFog(); break; 607 case 762: drawFog(); 608 break; 609 case 771: drawFog(); break; 610 case 781: drawFog(); break; 611 612 613 default:break; 614 } 615} 616 617 618 619void drawFog() 620{ 621 String command 622 = "weatherIcon.pic=13"; 623 Serial.print(command); 624 endNextionCommand(); 625} 626 627void 628 drawHeavySnowfall() 629{ 630 String command = "weatherIcon.pic=8"; 631 Serial.print(command); 632 633 endNextionCommand(); 634} 635 636void drawModerateSnowfall() 637{ 638 String 639 command = "weatherIcon.pic=8"; 640 Serial.print(command); 641 endNextionCommand(); 642} 643 644void 645 drawLightSnowfall() 646{ 647 String command = "weatherIcon.pic=11"; 648 Serial.print(command); 649 650 endNextionCommand(); 651} 652 653void drawHeavyRain() 654{ 655 String command 656 = "weatherIcon.pic=10"; 657 Serial.print(command); 658 endNextionCommand(); 659} 660 661void 662 drawModerateRain() 663{ 664 String command = "weatherIcon.pic=6"; 665 Serial.print(command); 666 667 endNextionCommand(); 668} 669 670void drawLightRain() 671{ 672 String command 673 = "weatherIcon.pic=6"; 674 Serial.print(command); 675 endNextionCommand(); 676} 677 678void 679 drawLightRainWithSunOrMoon() 680{ 681 String command = "weatherIcon.pic=7"; 682 683 Serial.print(command); 684 endNextionCommand(); 685} 686void drawThunderstorm() 687{ 688 689 String command = "weatherIcon.pic=3"; 690 Serial.print(command); 691 endNextionCommand(); 692} 693 694void 695 drawClearWeather() 696{ 697 String command = "weatherIcon.pic=4"; 698 Serial.print(command); 699 700 Serial.write(0xff); 701 Serial.write(0xff); 702 Serial.write(0xff); 703} 704 705void 706 drawCloud() 707{ 708 String command = "weatherIcon.pic=9"; 709 Serial.print(command); 710 711 endNextionCommand(); 712} 713 714void drawFewClouds() 715{ 716 String command 717 = "weatherIcon.pic=5"; 718 Serial.print(command); 719 endNextionCommand(); 720} 721 722 723 724// 725 HTTP server handling 726 727void handle_OnConnect() { 728 729 Temperature = dht.getTemperature(); 730 // Gets the values of the temperature 731 Humidity = dht.getHumidity(); // Gets 732 the values of the humidity 733 734 if (!isnan(temperaturein)) 735 { 736 server.send(200, 737 "text/html", SendHTML(temperaturein,temperaturein,humidityin)); 738 Serial.print("Temperature:"); 739 740 Serial.println(dht.getTemperature()); 741 } 742 if (!isnan(temperaturein)) 743 744 { 745 server.send(200, "text/html", SendHTML(backuptemp,backuptemp,backuphumi)); 746 747 Serial.print("Temperature:"); 748 Serial.println(dht.getTemperature()); 749 750 } 751} 752 753void handle_NotFound(){ 754 server.send(404, "text/plain", 755 "Not found"); 756} 757 758String SendHTML(float TempCstat,float TempFstat,float 759 Humiditystat){ 760 String ptr = "<!DOCTYPE html> <html>\ 761"; 762 ptr +="<head><meta 763 name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0, user-scalable=no\\">\ 764"; 765 766 ptr +="<link href=\\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\\" 767 rel=\\"stylesheet\\">\ 768"; 769 ptr +="<title>ESP32 Weather Report</title>\ 770"; 771 772 ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 773 0px auto; text-align: center;color: #333333;}\ 774"; 775 ptr +="body{margin-top: 776 50px;}\ 777"; 778 ptr +="h1 {margin: 50px auto 30px;}\ 779"; 780 ptr +=".side-by-side{display: 781 inline-block;vertical-align: middle;position: relative;}\ 782"; 783 ptr +=".humidity-icon{background-color: 784 #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\ 785"; 786 787 ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 788 160px;text-align: left;}\ 789"; 790 ptr +=".humidity{font-weight: 300;font-size: 791 60px;color: #3498db;}\ 792"; 793 ptr +=".temperature-icon{background-color: #f39c12;width: 794 30px;height: 30px;border-radius: 50%;line-height: 40px;}\ 795"; 796 ptr +=".temperature-text{font-weight: 797 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\ 798"; 799 800 ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\ 801"; 802 803 ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: 804 -20px;top: 15px;}\ 805"; 806 ptr +=".data{padding: 10px;}\ 807"; 808 ptr +="</style>\ 809"; 810 811 ptr +="</head>\ 812"; 813 ptr +="<body>\ 814"; 815 816 ptr +="<div id=\\"webpage\\">\ 817"; 818 819 820 ptr +="<h1>ESP32 Weather Report</h1>\ 821"; 822 ptr +="<div class=\\"data\\">\ 823"; 824 825 ptr +="<div class=\\"side-by-side temperature-icon\\">\ 826"; 827 ptr +="<svg 828 version=\\"1.1\\" id=\\"Layer_1\\" xmlns=\\"http://www.w3.org/2000/svg\\" 829 xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" x=\\"0px\\" y=\\"0px\\"\ 830"; 831 832 ptr +="width=\\"9.915px\\" height=\\"22px\\" viewBox=\\"0 0 9.915 22\\" 833 enable-background=\\"new 0 0 9.915 22\\" xml:space=\\"preserve\\">\ 834"; 835 836 ptr +="<path fill=\\"#FFFFFF\\" d=\\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\ 837"; 838 839 ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\ 840"; 841 842 ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\ 843"; 844 845 ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\ 846"; 847 848 ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\\"/>\ 849"; 850 851 ptr +="</svg>\ 852"; 853 ptr +="</div>\ 854"; 855 ptr +="<div class=\\"side-by-side 856 temperature-text\\">Temperature</div>\ 857"; 858 ptr +="<div class=\\"side-by-side 859 temperature\\">"; 860 ptr +=(float)TempCstat; 861 ptr +="<span class=\\"superscript\\">C</span></div>\ 862"; 863 864 ptr +="</div>\ 865"; 866 ptr +="<div class=\\"data\\">\ 867"; 868 ptr +="<div 869 class=\\"side-by-side humidity-icon\\">\ 870"; 871 ptr +="<svg version=\\"1.1\\" 872 id=\\"Layer_2\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\" 873 x=\\"0px\\" y=\\"0px\\"\ 874\\"; width=\\"12px\\" height=\\"17.955px\\" viewBox=\\"0 875 0 13 17.955\\" enable-background=\\"new 0 0 13 17.955\\" xml:space=\\"preserve\\">\ 876"; 877 878 ptr +="<path fill=\\"#FFFFFF\\" d=\\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\ 879"; 880 881 ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\\"></path>\ 882"; 883 884 ptr +="</svg>\ 885"; 886 ptr +="</div>\ 887"; 888 ptr +="<div class=\\"side-by-side 889 humidity-text\\">Humidity</div>\ 890"; 891 ptr +="<div class=\\"side-by-side 892 humidity\\">"; 893 ptr +=(int)Humiditystat; 894 ptr +="<span class=\\"superscript\\">%</span></div>\ 895"; 896 897 ptr +="</div>\ 898"; 899 900 ptr +="</div>\ 901"; 902 ptr +="</body>\ 903"; 904 905 ptr +="</html>\ 906"; 907 return ptr; 908} 909
Downloadable files
Schematic
Schematic of Project
Schematic

HMI file
Nextion editor uses the HMI file in order to edit or produce the .tft file needed for Nextion 3.2 Display to work. After the .tft file is produced, an SD card is needed in order to insert the file into the display.
HMI file
HMI file
Nextion editor uses the HMI file in order to edit or produce the .tft file needed for Nextion 3.2 Display to work. After the .tft file is produced, an SD card is needed in order to insert the file into the display.
HMI file
Circuit
Circuit

Schematic
Schematic of Project
Schematic

Comments
Only logged in users can leave comments