9浏览
查看: 9|回复: 2

[项目] 【Arduino 动手做】ESP32 和 Nextion 的原子钟和天气

[复制链接]
使用 ESP32 板和 Nextion 2.4 英寸 (240x320),您可以从互联网获得准确的时间和天气预报。

准确的时间和天气数据对每个人都有用。您可以花 25-30 欧元购买一个气象站,但只有其中一些将时间同步到 Atomic Clock 服务器。更不用说天气了:充其量,有些项目只有一个用于温度和湿度的室外传感器。从这些,也许还有一个大气压力传感器,可以估计出天气预报?为什么不获得准确的预报,并每小时更新一次呢!您只需通过您的家庭互联网提供商进行阅读,但使用您自己制作的设备,在 Arduino IDE(集成开发环境)下编程。

这不是互联网上第一个可用的此类项目。我们的灵感来自:
http://www.plastibots.com/index. ... n-tft-with-esp8266/
我们使用 ESP32,它的文档要少得多。
警告:JSON 解码库 https://github.com/bblanchon/ArduinoJson 已更新,因此我的代码也需要尽快更新!下面给出的代码与最新的库不兼容。

目的
它仅使用可靠的时间和天气数据。房屋周围的传感器从来都不是处于标准条件(阴影、离地高度、精度等),并且这些值可能会产生误导。来自互联网的天气预报是专业和官方的。时间每小时调整一次,因此可以预期最大误差为 1 秒(不是每月,不是每年,而是永久)。


【Arduino 动手做】ESP32 和 Nextion 的原子钟和天气图1

【Arduino 动手做】ESP32 和 Nextion 的原子钟和天气图2

【Arduino 动手做】ESP32 和 Nextion 的原子钟和天气图3

驴友花雕  中级技神
 楼主|

发表于 3 小时前

【Arduino 动手做】ESP32 和 Nextion 的原子钟和天气

项目代码

  1. /* Upload this project to GeekWorm ESP32-C1 using :
  2. *  -selected board: >>SparkFun ESP32 Thing<< or >> Wemos WiFi& Bluetooth battery<<
  3. *  - set it to 40MHz (enough for this project)
  4. *  -upload speed: 115200 : IMPORTANT!
  5. *  -select available COM port
  6. *  Connect USB direct to computer (200 mA required +50 mA for LCD) or external power (5V-350mA min/500 mA better)
  7. *  If not enough current available: Brownout error!
  8. *  Pins: Geekworm ESP32 <--> Nextion
  9. *                IO16     -    TX      
  10. *                IO17     -    RX
  11. *                GND      -    GND
  12. *                3.3V     -   +5v  (Nextion works also with 3.3V)
  13. *  Use Library: "nextion" with a modified file Nextion.h:        
  14. *  #define nextion Serial2       // This line is for ESP32 with hardware Serial2
  15. *  //#define USE_SOFTWARE_SERIAL //Comment this line if you use HardwareSerial
  16. *  The Nextion file is genrated using Nextion Editor: digital_clock-weather.HMI
  17. *  Once compiled, the file digital_clock-weather.tft can be transfered from File/Open Build folder to the transfer SD card.
  18. *  With the SD card inserted, Nextion updates the screen. Remove the SD card and connect the pins to ESP32.
  19. *      Project size: 512910/1310720 bytes (321152 compressed) with variables 47956/294912 bytes
  20. *  Receives and displays the weather forecast from the Weather Underground and then displays data using a
  21. * JSON decoder wx data to a NEXTION display.
  22. * Weather data received via WiFi connection from Weather Underground Servers and using their 'Forecast' API and data
  23. * is decoded using Copyright Benoit Blanchon's (c) 2014-2017 excellent JSON library.
  24. *
  25. * This MIT License (MIT) is copyright (c) 2017 by David Bird and permission is hereby granted, free of charge, to
  26. * any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software
  27. * without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, but not to sub-license and/or
  28. * to sell copies of the Software or to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  29. *   The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  30. *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  31. *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  32. *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. *   See more at http://dsbird.org.uk
  34. */
  35. HardwareSerial Serial2(2);        // Activate Serial communication 2 on ESP32 (RX=IO16 and TX=IO17)
  36. #include <TimeLib.h>              // Arduino Time library for 32 bit
  37. #include <WiFi.h>
  38. #include <WiFiClient.h>
  39. #include <WiFiUdp.h>
  40. #include <Nextion.h>              // Was modified to accept Serial1 hardware on ESP32
  41. #include <ArduinoJson.h>
  42. Nextion myNextion(nextion, 9600);             //create a Nextion object named myNextion using the nextion serial port
  43. char ssid[] = "aaaaaaaaaaaaaa";  //  your network SSID (name)  DEFINED in callserver();
  44. char pass[] = "bbbbbbbbbbbbbb";        // your network password
  45. const int ledPin =0,  timeZone = 2;     // East European Time (winter time)
  46. char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
  47. String RomanMonths[12] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"}; // January is month 0
  48. String month_of_year[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; // January is month 0
  49. int days,DST=0;
  50. unsigned long t0t=0, tsec=3600, t0w=0, wsec=3600; // Update weather after wsec [s] (30 min...2h is ok) and time after tsec (2..4h) {unsigned long < 4.29e9}
  51. //------ WEATHER NETWORK VARIABLES---------
  52. // Use your own API key by signing up for a free developer account at http://www.wunderground.com/weather/api/
  53. //Selected Plan: Stratus Developer: Calls Per Day= 500;  Calls Per Minute : 10
  54. String API_key       = "xxxxxxxxxxxxxxxxx";            // See: http://www.wunderground.com/weather/api/d/docs (change here with your KEY)
  55. String City          = "yyyyyyyyyyyyy";                   // Your home city : Weather Station ID: IBUCURET77
  56. String pws           = "zzzzzzzzzzzz";                  //  Dinicu Golescu 35 https://www.wunderground.com/personal-weather-station/dashboard?ID=IMUNICIP22&cm_ven=localwx_pwsdash
  57. String Country       = "CC";                          // Your country   
  58. String Conditions    = "conditions";                  // See: http://www.wunderground.com/weather/api/d/docs?d=data/index&MR=1
  59. char   wxserver[]    = "api.wunderground.com";        // Address for WeatherUnderGround
  60. // unsigned long        lastConnectionTime = 0;       // Last time you connected to the server, in milliseconds
  61. String SITE_WIDTH =  "900";
  62. String icon_set   =  "k";                             //
  63. String Units      =  "M";                             // Default use either M for Metric, X for Mixed and I for Imperial
  64. char* conds[]={""temp_c":"};
  65. // These are all (?) weather short definitions:
  66. String rain="Rain, Hail, Rain Showers, Ice Pellet Showers, Hail Showers, Small Hail Showers, Freezing Rain, Small Hail, rain";
  67. String thunde="Thunderstorm, Thunderstorms and Rain, Thunderstorms and Snow, Thunderstorms and Ice Pellets, Thunderstorms with Hail, Thunderstorms with Small Hail, chancetstorms, tstorms";
  68. String sunny="Clear, Unknown Precipitation, Unknown, sunny, unknown, clear";
  69. String cloudy="Overcast, cloudy";
  70. String chanceflurries="chanceflurries, flurries";
  71. String chancerain="Drizzle, Rain Mist, chancerain, chancesleet, sleet";
  72. String chancesnow="Snow Grains, Ice Crystals, Ice Pellets, Low Drifting Snow, Snow Blowing Snow Mist, Freezing Drizzle, chancesnow";
  73. String fog="Mist, Fog, FogPatches, Smoke, VolcanicAsh, WidespreadDust, Sand, Haze, Spray, DustWhirls, Sandstorm, LowDrifting WidespreadDust, LowDriftingSand, BlowingWidespreadDust, BlowingSand, FreezingFog, PatchesofFog, ShallowFog, fog, hazy";
  74. String mostlycloudy="MostlyCloudy, Squalls, FunnelCloud, mostlycloudy, partlysunny";
  75. String partlycloudy="PartlyCloudy, ScatteredClouds, mostlysunny, partlycloudy";
  76. String snow="Snow, Blowing Snow, Snow Showers, snow";
  77. float temp_c=0;
  78. int temp_e, nr=0;
  79. String wind_e, h_up, m_up, h_set, m_set;             // Data strings
  80. boolean timeok=false, foreok=false, condok=false, zzz=false;  // Update flags
  81. //-------------------------------------------------------------------------------------------
  82. //################ PROGRAM VARIABLES and OBJECTS ################
  83. // Conditions
  84. String webpage, city, country, date_time, observationtime,
  85.        DWDay0, DMon0, DDateDa0, DDateMo0, DDateYr0, Dicon0, Dicon_url0, DHtemp0, DLtemp0, DHumi0, Dpop0, DRain0, DW_mph0, DW_dir0, DW_dir_deg0, DWeather0, Dconditions0, DcurrentTemp, Txw1,
  86.        DWDay1, DMon1, DDateDa1, DDateMo1, DDateYr1, Dicon1, Dicon_url1, DHtemp1, DLtemp1, DHumi1, DPop1, DRain1, DW_mph1, DW_dir1, DW_dir_deg1, DWeather1, Dconditions1,
  87.        DWDay2, DMon2, DDateDa2, DDateMo2, DDateYr2, Dicon2, Dicon_url2, DHtemp2, DLtemp2, DHumi2, DPop2, DRain2, DW_mph2, DW_dir2, DW_dir_deg2, DWeather2, Dconditions2,
  88.        DWDay3, DMon3, DDateDa3, DDateMo3, DDateYr3, Dicon3, Dicon_url3, DHtemp3, DLtemp3, DHumi3, DPop3, DRain3, DW_mph3, DW_dir3, DW_dir_deg3, DWeather3, Dconditions3,
  89.        DWDay4, DMon4, DDateDa4, DDateMo4, DDateYr4, Dicon4, Dicon_url4, DHtemp4, DLtemp4, DHumi4, DPop4, DRain4, DW_mph4, DW_dir4, DW_dir_deg4, DWeather4, Dconditions4;
  90. char buffer[100] = {0};
  91. char buffer_hour[10] = {0};
  92. char Txtweather[200];
  93. //-------------------------------------------------------------------------------------------
  94. // NTP Servers:
  95. //static const char ntpServerName[] = "ntps1-0.cs.tu-berlin.de";    // Chosen Atomic Time server
  96. static const char ntpServerName[] = "0.pool.ntp.org";            // Recommended server
  97. const int NTP_PACKET_SIZE = 48;     // NTP time stamp is in the first 48 bytes of the message
  98. byte packetBuffer[ NTP_PACKET_SIZE];    //buffer to hold incoming and outgoing packets
  99. // A UDP instance to let us send and receive packets over UDP
  100. WiFiUDP Udp;                        // Initialize User Datagram Protocol (UDP)
  101. unsigned int localPort = 8888;      // local port to listen for UDP time packets
  102. //-------------------------------------------------------------------------------------------
  103. // List of the functions defined below:
  104. time_t getNtpTime();                // Convert received seconds into HH:MM:SS, YY-MO-DD     
  105. void sendNTPpacket(IPAddress &address);  // Require site data
  106. void digitalClockDisplay();         // See below function to print time on Nextion
  107. void weatherDisplay();              // See below function to print weather on Nextion
  108. void obtain_forecast (String forecast_type); // See below function to get weather data
  109. #define min(a,b) ((a)<(b)?(a):(b)); // Define the min(a,b) function!
  110. // =======================================================================
  111. void callserver(){
  112. // Start by connecting to a local WiFi router
  113. // Since WiFi.disconnect(true)erases ssid&pass, define these here each time.
  114. // =========================!!!!!===================================
  115.   char ssid[] = "RomTelecom-WEP-B086";  //  your network SSID (name)
  116.   char pass[] = "AYPDG7J5TFKGF";        // your network password
  117. // =========================!!!!!===================================
  118.     Serial.println(F("============================================"));
  119.     Serial.print(F("Connecting to "));  Serial.print(ssid); Serial.print(F(" & ")); Serial.println(pass);
  120.     delay(200);
  121.   WiFi.begin(ssid, pass);
  122.     Serial.println(F(">>>>>>>")); Serial.print("Connecting...");
  123.   myNextion.setComponentText("g0","Connecting..."); // Scroll weather description text !
  124.   delay(300);
  125.   int iter=0;           // Try several times to connect to local router
  126.   while (WiFi.status() != WL_CONNECTED  && iter<50) {
  127.     // LED blink as long as the connection is not establihed
  128.     delay(500);
  129.     digitalWrite(ledPin, LOW);
  130.     delay(500);
  131.     digitalWrite(ledPin, HIGH);
  132.     Serial.print(".");
  133.     iter++;
  134.   }
  135.   if (iter<50){
  136.       digitalWrite(ledPin, HIGH);               // Led OFF
  137.       Serial.print("WiFi connected to local"); Serial.print("IP : ");
  138.       Serial.println(WiFi.localIP());   Serial.println("********************************");
  139.       myNextion.setComponentText("g0","Connected. Updating soon!"); // Scroll weather description text !
  140.       delay(300);
  141.       // At this stage the ESP32 is connected to the local network
  142.   }
  143.   else{
  144.       digitalWrite(ledPin, LOW);              // Led ON
  145.       Serial.println(F("!! WiFi connection failed !!!"));
  146.       Serial.println(F("!!!!!!!!!!!!!!!!!!!!!!!!!!!!"));
  147.       WiFi.disconnect(true);
  148.       delay(2000);
  149.   }
  150. }
  151. void setup()
  152. {
  153.   Serial.begin(115200);            // USB communication with Serial Monitor
  154.   Serial2.begin(9600);             // Initiate 2-nd UART towards Nextion
  155.   pinMode(ledPin, OUTPUT);         // Set Led pin as output
  156.   myNextion.sendCommand("rest");   // reset Nextion
  157.   myNextion.sendCommand("dim=40");       // Dim to 40% the display
  158.   while(WiFi.status() != WL_CONNECTED){
  159.     callserver();                  // Try to connect to local server
  160.   }
  161.         
  162.   Serial.print("Synchronizing time: ");
  163.   Serial.println(ntpServerName);
  164.   setSyncProvider(getNtpTime);        // Set the MCU time from Internet: the Atomic Clock Time
  165.   setSyncInterval(86400);              // Requiring sync. after ... seconds
  166.                                       // but will fail if WiFi is turned off.
  167.   Serial.print("Next sync. in ");Serial.print(tsec);Serial.println(" s");
  168.   Udp.stop();   // STOP UDP
  169.   delay(500);
  170.   obtain_forecast("forecast");     // Get weather forecast
  171.   obtain_forecast("conditions");   // Get local conditions
  172.   digitalWrite(ledPin, HIGH);     // LED OFF if OK
  173.   Serial.println("==============================================");
  174.   Serial.print("Weather for current time:");
  175.   Serial.print(hour());Serial.print(":");Serial.print(minute());Serial.print(":");Serial.println(second());
  176.   Serial.print("Time status:");Serial.println(timeok);
  177.   Serial.print("Forecast status:");Serial.println(foreok);
  178.   Serial.print("Conditions status:");Serial.println(condok);
  179.   
  180.   Serial.println(DWDay1);  Serial.println(Dicon1);  Serial.println(DHtemp1);
  181.   Serial.println(DLtemp1);  Serial.println(DHumi1);  Serial.println(DW_mph1);
  182.   Serial.println(DWDay2);  Serial.println(Dicon2);  Serial.println(DHtemp2);
  183.   Serial.println(DLtemp2);  Serial.println(DHumi2);  Serial.println(DW_mph2);
  184.   Serial.println(DWDay3);  Serial.println(Dicon3);  Serial.println(DHtemp3);
  185.   Serial.println(DLtemp3);  Serial.println(DHumi3);  Serial.println(DW_mph3);
  186.   Serial.println("--Local weather, now: --");
  187.   Serial.println(Txtweather);  Serial.println(temp_e);  Serial.println(wind_e);
  188.   Serial.print(h_up);Serial.print(":"); Serial.println(m_up);
  189.   Serial.print(h_set);Serial.print(":");Serial.println(m_set);
  190.    vTaskDelay(100/portTICK_RATE_MS);
  191.   Serial.println("==============================================");
  192.   digitalClockDisplay();    // Send clock data to Nextion
  193.   vTaskDelay(100/portTICK_RATE_MS);
  194.   weatherDisplay();         // Send weather data to Nextion
  195.   nr=min(tsec, wsec);
  196.   Serial.print("WiFi off for "); Serial.print(nr); Serial.println(" s : after Setup");
  197.   WiFi.disconnect(true);   // STOP WIFI!!
  198.   vTaskDelay(100/portTICK_RATE_MS);
  199.   nr=0;
  200. }
  201. time_t prevDisplay = 0; // moment when the clock was displayed
  202.   
  203. void loop()
  204. {
  205. // Every second: update time on Nextion
  206.   if (now() != prevDisplay) {       // ..update the display only if time has changed [every sec.]
  207.      prevDisplay = now();
  208.     //----------------------------------------
  209.     // Compute DST hour if server is not a local one:
  210.     DST=0;
  211.     if (month()>3 && month()<10)            
  212.      DST=1;
  213.      days=31-((5*year())/4+4)%7;
  214.     if (month()==3 && day()>=days)
  215.      DST=1;
  216.      days=31-((5*year())/4+1)%7;
  217.     if (month()==10 && day()<days)
  218.         DST=1;
  219.     //----------------------------------------
  220.      digitalClockDisplay();        // Send clock data to Nextion every second
  221.   }
  222.   
  223.   if(millis() - t0t > tsec*1e3) {   // after every time interval "tsec"
  224.     if (WiFi.status() != WL_DISCONNECTED)
  225.        WiFi.disconnect(true);
  226.      // if (timeStatus() == timeNeedsSync){
  227.      // Firstly: connect to local router (WiFi might be disconnected)
  228.     vTaskDelay(100/portTICK_RATE_MS);
  229.     while(WiFi.status() != WL_CONNECTED){
  230.       callserver();                  // Try to connect to local server
  231.       if(WiFi.status() != WL_CONNECTED){
  232.          delay(5000);
  233.          Serial.println("RESET ESP32 in loop() for time update !!!!");
  234.          ESP.restart();             // Restart ESP32! So, the code is reinitialized!!              
  235.       }
  236.       // Should be connected at this point, or MCU restarted ???
  237.     }
  238.     if(WiFi.status() == WL_CONNECTED){
  239.      Serial.print("Synchronizing time: ");  Serial.println(ntpServerName);
  240.      // The "Time" library is supposed to connect to time server now
  241.      
  242.      setSyncProvider(getNtpTime);        // Set the MCU time from Internet: the Atomic Clock Time
  243.      setSyncInterval(86400);              // Requiring sync. after ... seconds
  244.                                       // but will fail if WiFi is turned off.
  245.      Serial.print("Next sync. in ");Serial.print(tsec);Serial.println(" s");
  246.      Udp.stop();   // STOP UDP
  247.      
  248.      delay(500);
  249.      obtain_forecast("forecast");     // Get weather forecast
  250.      obtain_forecast("conditions");
  251.      
  252.      if (timeok==true){
  253.       t0t=millis();
  254.       myNextion.setComponentValue("bt3",0);  // Button3 [:] has blue bkgd. if time is updated ...
  255.       myNextion.setComponentValue("bt4",0);  // Button4 [:] has blue bkgd. if time is updated ...
  256.       WiFi.disconnect(true);
  257.       Serial.print(F("WiFi off for ")); Serial.print(tsec); Serial.println(F(" s : after Time & Weather sync.!"));
  258.      }
  259.      else{
  260.       myNextion.setComponentValue("bt3",1);  // Button3 [:] has orange bkgd. if time is not updated ...
  261.       myNextion.setComponentValue("bt4",1);  // Button4 [:] has orange bkgd. if time is not updated ...
  262.       delay(500);
  263.       WiFi.disconnect(true);
  264.       Serial.print(F("WiFi off for ")); Serial.print(tsec); Serial.println(F(" s : Failed sync.!"));
  265.      }
  266.     }
  267.     else{
  268.       t0t=tsec*1e3-60000;         // Repeat updating in 1 minute
  269.       WiFi.disconnect(true);
  270.       Serial.println(F("!! WiFi off after failing to connect!"));
  271.     }
  272.    // Just for debugging, print results on Serial Monitor attached via USB
  273.        Serial.println(F("=============================================="));   
  274.        Serial.print(F("Weather for current time:"));
  275.        Serial.print(hour());Serial.print(":");Serial.print(minute());Serial.print(":");Serial.println(second());
  276.        nr++;
  277.        Serial.print("Update no:");Serial.println(nr);
  278.        Serial.print("Time status:");Serial.println(timeok);
  279.        Serial.print("Forecast status:");Serial.println(foreok);
  280.        Serial.print("Conditions status:");Serial.println(condok);
  281.        Serial.println(F("----------------------------------------------"));
  282.        Serial.println(DWDay1);   Serial.println(Dicon1);   Serial.println(DHtemp1);
  283.        Serial.println(DLtemp1);   Serial.println(DHumi1);   Serial.println(DW_mph1);
  284.        Serial.println(DWDay2);   Serial.println(Dicon2);   Serial.println(DHtemp2);
  285.        Serial.println(DLtemp2);   Serial.println(DHumi2);   Serial.println(DW_mph2);
  286.        Serial.println(DWDay3);   Serial.println(Dicon3);   Serial.println(DHtemp3);
  287.        Serial.println(DLtemp3);   Serial.println(DHumi3);   Serial.println(DW_mph1);
  288.        Serial.println(Txtweather);   Serial.println(temp_e);   Serial.println(wind_e);
  289.        Serial.print(h_up);Serial.print(":"); Serial.println(m_up);
  290.        Serial.print(h_set);Serial.print(":");Serial.println(m_set);
  291.        // In any case write weather data to Nextion
  292.         weatherDisplay();                  // Send weather data to Nextion
  293.    
  294. }
  295.   
  296.   //==============================================================================
  297.   // During night hours 0-6, turn off display, but reactivate if touched  
  298.     if (hour()<6 && zzz==false){
  299.         
  300.         myNextion.sendCommand("dim=0");       // Dim to 0 the display
  301.         // myNextion.sendCommand("thup=1");      // Remain responsive to touch
  302.         delay(1000);
  303.         zzz=true;                             // Sleeping flag ON, to do this once/day.
  304.         Serial.println(F("Display sleeping!"));
  305.         //  myNextion.sendCommand("sleep=1");   // Go to sleep Nextion!!
  306.     }
  307.     else if (hour()>=6 && zzz==true){
  308.         myNextion.sendCommand("dim=40");       // Dim to 40% the display
  309.         //myNextion.sendCommand("wup");         //   wake-up Nextion
  310.         delay(1000);
  311.         zzz=false;                             // Not-sleelping flag
  312.         Serial.println(F("Display activated!"));  
  313.     }  
  314.   //==============================================================================
  315.     if (millis() < t0t){
  316.       t0t=millis();                    // After millis reached the limit, reset counters
  317.       Serial.print("Time counter t0t reset!");
  318.     }
  319.       
  320.     if (millis() < t0w){
  321.       t0w=millis();                    // After millis reached the limit, reset counters
  322.       Serial.print("Weather counter t0w reset!");  
  323.     }
  324.       
  325. }
  326. void digitalClockDisplay()
  327. {// Write Clock data on Nextion
  328.   // Display the time. Digital clock.
  329.   // Send a number to a number cell of Nextion
  330.    if (DST==1)
  331.     myNextion.setComponentValue("n0",hour()+1);
  332.   else
  333.     myNextion.setComponentValue("n0",hour());   
  334.   myNextion.setComponentValue("n1",minute());
  335.   myNextion.setComponentValue("n2",second());
  336.   myNextion.setComponentText("t3",daysOfTheWeek[weekday()-1]);
  337.   // Send strings to string cells of Nextion
  338.   myNextion.setComponentText("t4", String(day()));
  339.   //myNextion.setComponentText("t5", String(month()));
  340.   myNextion.setComponentText("t5", month_of_year[month()-1]);
  341.   myNextion.setComponentText("t6", String(year()));
  342. }
  343. void weatherDisplay()        
  344. {// Write weather data on Nextion
  345.   myNextion.sendCommand("page 0");
  346.   myNextion.setComponentValue("n3",temp_e);    // to numeric obj. n3 Temp. outside now
  347.   myNextion.setComponentText("t8",wind_e);     // to text obj. 8 Wind speed outside now
  348.   myNextion.setComponentText("t10",DHtemp1);   // to text obj. 10  Max Temp. of the day
  349.   myNextion.setComponentText("t11",DLtemp1);   // to text obj. 11  Min Temp. of the day
  350.   myNextion.setComponentText("t12",DHumi1);    // to text obj. 12  Humidity  of the day
  351.   myNextion.setComponentText("g0",Txtweather); // Scroll weather description text + minutes after update!
  352.   myNextion.setComponentText("t33",h_up+":"+m_up);    // to text obj. 33  Sun rise time  
  353.   myNextion.setComponentText("t34",h_set+":"+m_set);    // to text obj. 33  Sun set time  
  354.   
  355.   myNextion.sendCommand("page 1");
  356.   myNextion.setComponentText("t14",daysOfTheWeek[(weekday())%7]);  // Swow tomorow
  357.   myNextion.setComponentText("t20",DHtemp2);   //to text obj. 20 Estimated High Temp.
  358.   myNextion.setComponentText("t21",DLtemp2);  // Estimated Low Temp.
  359.   myNextion.setComponentText("t22",DHumi2);   // Estimated humidity
  360.   myNextion.setComponentText("t31",DW_mph2);  // Estimated wind speed
  361.   myNextion.setComponentText("t15",daysOfTheWeek[(weekday()+1)%7]); // Swow after tomorow
  362.   myNextion.setComponentText("t26",DHtemp3);  //to text obj. 26 Estimated High Temp.
  363.   myNextion.setComponentText("t27",DLtemp3);  // Estimated Low Temp.
  364.   myNextion.setComponentText("t28",DHumi3);   // Estimated humidity
  365.   myNextion.setComponentText("t32",DW_mph3);  // Estimated wind speed
  366.   myNextion.sendCommand("page 0");
  367.     // Now change the pictures accordingly:
  368.   if(Dicon1=="clear")
  369.     myNextion.sendCommand("p0.pic=0");
  370.   if(Dicon1=="partlycloudy")
  371.     myNextion.sendCommand("p0.pic=1");
  372.   if(Dicon1=="cloudy"||Dicon1=="mostlycloudy")
  373.     myNextion.sendCommand("p0.pic=2");
  374.   if(Dicon1=="rain" || Dicon1=="chancerain")
  375.     myNextion.sendCommand("p0.pic=3");
  376.   if(Dicon1=="snow")
  377.     myNextion.sendCommand("p0.pic=4");
  378.   if(Dicon1=="fog" || Dicon1=="hazy" || Dicon1=="mist")
  379.     myNextion.sendCommand("p0.pic=5");
  380.   if(Dicon1=="thunderstorm" || Dicon1=="chancetstorms")
  381.     myNextion.sendCommand("p0.pic=6");
  382.   if(Dicon1=="sleet" || Dicon1=="chancetstorms")
  383.     myNextion.sendCommand("p0.pic=6");
  384.   myNextion.sendCommand("page 1");        // Go to page 1
  385.   if(Dicon2=="clear")
  386.     myNextion.sendCommand("p1.pic=0");
  387.   if(Dicon2=="partlycloudy")
  388.     myNextion.sendCommand("p1.pic=1");
  389.   if(Dicon2=="cloudy"||Dicon1=="mostlycloudy")
  390.     myNextion.sendCommand("p1.pic=2");
  391.   if(Dicon2=="rain" || Dicon2=="chancerain")
  392.     myNextion.sendCommand("p1.pic=3");
  393.   if(Dicon2=="snow")
  394.     myNextion.sendCommand("p1.pic=4");
  395.   if(Dicon2=="fog" || Dicon2=="hazy" || Dicon2=="mist")
  396.     myNextion.sendCommand("p1.pic=5");
  397.   if(Dicon2=="thunderstorm" || Dicon2=="chancetstorms")
  398.     myNextion.sendCommand("p1.pic=6");
  399.   if(Dicon3=="clear")
  400.    myNextion.sendCommand("p2.pic=0");
  401.   if(Dicon3=="partlycloudy")
  402.    myNextion.sendCommand("p2.pic=1");
  403.   if(Dicon3=="cloudy"||Dicon1=="mostlycloudy")
  404.    myNextion.sendCommand("p2.pic=2");
  405.   if(Dicon3=="rain" || Dicon3=="chancerain")
  406.    myNextion.sendCommand("p2.pic=3");
  407.   if(Dicon3=="snow")
  408.    myNextion.sendCommand("p2.pic=4");
  409.   if(Dicon3=="fog" || Dicon3=="hazy" || Dicon3=="mist")
  410.     myNextion.sendCommand("p2.pic=5");
  411.   if(Dicon3=="thunderstorm" || Dicon3=="chancetstorms")
  412.     myNextion.sendCommand("p2.pic=6");
  413.   myNextion.sendCommand("page 0");        // Come back to page 0
  414.   if (condok==true)
  415.     myNextion.setComponentValue("bt1",1);  // Button1 is green if local conditions are updated ...
  416.   else
  417.     myNextion.setComponentValue("bt1",0);  // else it is red.
  418.    
  419.   if (foreok==true)
  420.     myNextion.setComponentValue("bt2",1);  // Button2 is green if forecast is updated ...
  421.   else
  422.     myNextion.setComponentValue("bt2",0);  // else it is red.  
  423. }
  424. /*-------- NTP code ----------*/
  425. time_t getNtpTime()
  426. { //PaulStoffregen/Time
  427.    while(WiFi.status() != WL_CONNECTED){
  428.       callserver();                  // Try (50 times) to connect to the local server
  429.       if(WiFi.status() != WL_CONNECTED){
  430.         delay(3000);
  431.         ESP.restart();               // Restart ESP32! So, the code is reinitialized!!   
  432.       }
  433.       // Should be connected at this point, or MCU restarted
  434.    }
  435.   Udp.begin(localPort);
  436.   IPAddress ntpServerIP; // NTP server's ip address
  437.   
  438.   // while (Udp.parsePacket() > 0) ; // discard any previously received packets
  439.   Serial.print("Transmit NTP Request to:");
  440.   WiFi.hostByName(ntpServerName, ntpServerIP);
  441.   Serial.print(ntpServerName);  Serial.print("= ");  Serial.println(ntpServerIP);
  442.   uint32_t beginWait = millis();
  443.   sendNTPpacket(ntpServerIP);
  444.   
  445.   while (millis() - beginWait < 5000) {
  446.     int size = Udp.parsePacket();
  447.     if (size >= NTP_PACKET_SIZE) {
  448.       Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
  449.       Serial.println(F("Received NTP Response. Successfully updated Time..."));
  450.       Serial.println(F("====================================="));
  451.       timeok=true;
  452.       unsigned long secsSince1900;
  453.       // convert four bytes starting at location 40 to a long integer
  454.       secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
  455.       secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
  456.       secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
  457.       secsSince1900 |= (unsigned long)packetBuffer[43];
  458.       return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;  // maybe add +1 for update delays?
  459.       // Exit function here.
  460.     }
  461.     else
  462.       timeok=false;
  463.   }
  464.   Udp.endPacket();
  465.   Serial.println("No NTP Response :-(");
  466.   Serial.println("Time is not synchronized");
  467.   Serial.println("RESET ESP32 in getNtpTime() !!!!");
  468.   ESP.restart();               // Restart ESP32! So, the code is reinitialized!!   
  469.   return 0; // return 0 if unable to get the time
  470. }
  471. void sendNTPpacket(IPAddress& address)
  472. // send an NTP request to the time server at the given address
  473. {
  474.   Serial.println("sending NTP packet...");
  475.   // set all bytes in the buffer to 0
  476.   memset(packetBuffer, 0, NTP_PACKET_SIZE);
  477.   // Initialize values needed to form NTP request
  478.   // (see URL above for details on the packets)
  479.   packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  480.   packetBuffer[1] = 0;     // Stratum, or type of clock
  481.   packetBuffer[2] = 6;     // Polling Interval
  482.   packetBuffer[3] = 0xEC;  // Peer Clock Precision
  483.   // 8 bytes of zero for Root Delay & Root Dispersion
  484.   packetBuffer[12]  = 49;
  485.   packetBuffer[13]  = 0x4E;
  486.   packetBuffer[14]  = 49;
  487.   packetBuffer[15]  = 52;
  488.   // all NTP fields have been given values, now
  489.   // you can send a packet requesting a timestamp:
  490.   Udp.beginPacket(address, 123); //NTP requests are to port 123
  491.   Udp.write(packetBuffer, NTP_PACKET_SIZE);
  492.   Udp.endPacket();
  493. }
  494. void obtain_forecast (String forecast_type) {
  495.   static char RxBuf[8704];
  496.   String request;
  497.   if (forecast_type=="forecast")
  498.     request  = "GET /api/" + API_key + "/"+ forecast_type + "/q/" + Country + "/" + City + ".json HTTP/1.1\r\n"; // Request Country/City
  499.   else
  500.     request  = "GET /api/" + API_key + "/"+ forecast_type + "/astronomy/q/geolookup/pws:" + pws + ".json HTTP/1.1\r\n";  // Request data by pws station
  501.   // http://api.wunderground.com/api/7a4e220afaaf6547/conditions/q/geolookup/pws:IBUCURET77.json
  502.   request += F("User-Agent: Weather Webserver v");
  503.   //request += version;
  504.   request += F("\r\n");
  505.   request += F("Accept: */*\r\n");
  506.   request += "Host: " + String(wxserver) + "\r\n";
  507.   request += F("Connection: close\r\n");
  508.   request += F("\r\n");
  509.   Serial.println(F("------------------------------------------"));
  510.   Serial.print(F("Connecting to ")); Serial.println(wxserver);
  511.   WiFiClient httpclient;
  512.   if (!httpclient.connect(wxserver, 80)) {
  513.     Serial.println(F("connection failed"));
  514.     httpclient.flush();  //Waits until all outgoing characters in buffer have been sent (forever if lost connection!)
  515.     httpclient.stop();
  516.     WiFi.disconnect(true);
  517.     vTaskDelay(1000/portTICK_RATE_MS);
  518.               ESP.restart();             // Restart ESP32! So, the code is reinitialized???
  519.     return;
  520.   }
  521.   vTaskDelay(100/portTICK_RATE_MS);
  522.   httpclient.print(request); //send the request to the server
  523.   httpclient.flush();  //Waits until all outgoing characters in buffer have been sent (forever if connection lost)
  524.   Serial.print(forecast_type); Serial.print(F(": "));
  525.   Serial.println("The request was sent to Weather server. Waiting for the response...");
  526.   vTaskDelay(100/portTICK_RATE_MS);
  527.   
  528.   // Collect http response headers and content from Weather Underground, discarding HTTP headers,
  529.   //   the content is JSON formatted and will be returned in RxBuf.
  530.   int    respLen = 0;
  531.   bool   skip_headers = true;
  532.   String rx_line;
  533.   unsigned long beginWait = millis();
  534.   while ((httpclient.connected() || httpclient.available()) && (millis() - beginWait < 10000)) {
  535.     //vTaskDelay(10/portTICK_RATE_MS);//works for keeping the watchdog fed when there is no other activity
  536.     if (skip_headers) {
  537.       rx_line = httpclient.readStringUntil('\n');
  538.       if (rx_line.length() <= 1) { // a blank line denotes end of headers
  539.         skip_headers = false;
  540.       }
  541.     }
  542.     else {
  543.       int bytesIn;
  544.       bytesIn = httpclient.read((uint8_t *)&RxBuf[respLen], sizeof(RxBuf) - respLen);
  545.       Serial.print(F("bytesIn: ")); Serial.println(bytesIn);
  546.       if (bytesIn > 0) {
  547.         respLen += bytesIn;           // Gather bytes in RxBuf
  548.         if (respLen > sizeof(RxBuf)) respLen = sizeof(RxBuf);
  549.         //vTaskDelay(10/portTICK_RATE_MS); //works for keeping the watchdog fed when there is no other activity        
  550.       }
  551.       else if (bytesIn < 0) {
  552.         vTaskDelay(200/portTICK_RATE_MS);
  553.         Serial.print("?");  // Appears very often, waiting for an answer!
  554.         vTaskDelay(200/portTICK_RATE_MS); //works for keeping the watchdog fed when there is no other activity        
  555.       }
  556.     }
  557.    vTaskDelay(100/portTICK_RATE_MS); //works for keeping the watchdog fed when there is no other activity        
  558.   }
  559.   httpclient.stop();
  560.   vTaskDelay(100/portTICK_RATE_MS); //works for keeping the watchdog fed when there is no other activity        
  561.    
  562.   RxBuf[respLen++] = '\0'; // Terminate the C string
  563.   // RxBuf contains now the server response, of length=respLen.
  564.   if (respLen<=1 && forecast_type == "forecast"){
  565.         foreok=false;     // If no data available return without changing forecast
  566.         return;
  567.   }
  568.   
  569.   if (respLen<=1 && forecast_type == "conditions"){
  570.         condok=false;     // If no data available return without changing conditions
  571.         return;
  572.   }  
  573.   
  574.   if (forecast_type == "forecast"){
  575.      if (showWeather_forecast(RxBuf)){
  576.         foreok=true;
  577.         vTaskDelay(50/portTICK_RATE_MS); //works for keeping the watchdog fed when there is no other activity        
  578.      }
  579.   }
  580.   if (forecast_type == "conditions"){
  581.      if (showWeather_conditions(RxBuf)){
  582.          condok=true;
  583.          vTaskDelay(50/portTICK_RATE_MS); //works for keeping the watchdog fed when there is no other activity        
  584.      }
  585.   }  
  586. }
  587. bool showWeather_forecast(char *json)
  588. {// Convert forecast received data into Strings and values
  589.   DynamicJsonBuffer jsonBuffer(8704);
  590.   char *jsonstart = strchr(json, '{');    // Look for first "{"
  591. // Serial.println(F("jsonstart ")); Serial.println(jsonstart); // This is input data
  592.   if (jsonstart == NULL) {
  593.     Serial.println(F("JSON data missing"));
  594.     return false;
  595.   }
  596.   json = jsonstart;
  597.   // Parse JSON
  598.   JsonObject& root = jsonBuffer.parseObject(json);
  599.   if (!root.success()) {
  600.     Serial.println(F("jsonBuffer.parseObject() failed"));
  601.     return false;
  602.   }
  603.   JsonObject& forecast = root["forecast"]["simpleforecast"];
  604.   String WDay1      = forecast["forecastday"][0]["date"]["weekday"];         DWDay1      = WDay1;
  605.   int DateDa1       = forecast["forecastday"][0]["date"]["day"];             DDateDa1    = DateDa1<10?"0"+String(DateDa1):String(DateDa1);
  606.   String Temp_mon   = forecast["forecastday"][0]["date"]["monthname"];
  607.   String Mon1       = forecast["forecastday"][0]["date"]["monthname_short"]; DMon1       = Mon1;
  608.   int DateYr1       = forecast["forecastday"][0]["date"]["year"];            DDateYr1    = String(DateYr1).substring(2);
  609.   observationtime   = "from " + String(DDateDa1) + " " + Temp_mon + ", " + DateYr1;
  610.   if (Units == "M" || Units == "X") {
  611.     String icon1         = forecast["forecastday"][0]["icon"];               Dicon1      = String(icon1);
  612.     String conditions1    = forecast["forecastday"][0]["conditions"];        Dconditions1   = String(conditions1);
  613.     int Htemp1        = forecast["forecastday"][0]["high"]["celsius"];       DHtemp1     = String(Htemp1);
  614.     int Ltemp1        = forecast["forecastday"][0]["low"]["celsius"];        DLtemp1     = String(Ltemp1);
  615.     int rain1         = forecast["forecastday"][0]["qpf_allday"]["mm"];      DRain1      = String(rain1)+"mm";
  616.     if (Units == "M") {int w_mph1 = forecast["forecastday"][0]["avewind"]["kph"];  DW_mph1 = String(w_mph1)+"km/h";}
  617.     else {int w_mph1   = forecast["forecastday"][0]["avewind"]["mph"];  DW_mph1 = String(w_mph1)+"mph";}
  618.   }
  619.   String icon_url1  = forecast["forecastday"][0]["icon_url"];           
  620.   Dicon_url1        = icon_url1.substring(0,icon_url1.indexOf("/i/c/")+5) + icon_set + icon_url1.substring(icon_url1.indexOf("/i/c/")+6);
  621.   String pop1       = forecast["forecastday"][0]["pop"];                     DPop1       = String(pop1);
  622.   String w_dir1     = forecast["forecastday"][0]["avewind"]["dir"];          DW_dir1     = String(w_dir1);
  623.   String w_dir_deg1 = forecast["forecastday"][0]["avewind"]["degrees"];      DW_dir_deg1 = String(w_dir_deg1);
  624.   int humi1         = forecast["forecastday"][0]["avehumidity"];             DHumi1      = String(humi1);
  625.   
  626.   String WDay2      = forecast["forecastday"][1]["date"]["weekday"];         DWDay2      = WDay2;
  627.   int DateDa2       = forecast["forecastday"][1]["date"]["day"];             DDateDa2    = DateDa2<10?"0"+String(DateDa2):String(DateDa2);
  628.   String Mon2       = forecast["forecastday"][1]["date"]["monthname_short"]; DMon2       = Mon2;
  629.   int DateYr2       = forecast["forecastday"][1]["date"]["year"];            DDateYr2    = String(DateYr2).substring(2);
  630.   if (Units == "M" || Units == "X") {
  631.     String icon2         = forecast["forecastday"][1]["icon"];              Dicon2      = String(icon2);
  632.     String conditions2    = forecast["forecastday"][1]["conditions"];       Dconditions2   = String(conditions2);
  633.     int Htemp2        = forecast["forecastday"][1]["high"]["celsius"];       DHtemp2     = String(Htemp2);
  634.     int Ltemp2        = forecast["forecastday"][1]["low"]["celsius"];        DLtemp2     = String(Ltemp2);
  635.     int rain2         = forecast["forecastday"][1]["qpf_allday"]["mm"];      DRain2      = String(rain2)+"mm";
  636.     if (Units == "M"){int w_mph2 = forecast["forecastday"][1]["avewind"]["kph"]; DW_mph2 = String(w_mph2)+"km/h";}
  637.     else {int w_mph2  = forecast["forecastday"][1]["avewind"]["mph"];        DW_mph2     = String(w_mph2)+"mph";
  638.     }
  639.   }
  640.   String icon_url2  = forecast["forecastday"][1]["icon_url"];           
  641.   Dicon_url2        = icon_url2.substring(0,icon_url2.indexOf("/i/c/")+5) + icon_set + icon_url2.substring(icon_url2.indexOf("/i/c/")+6);
  642.   String pop2       = forecast["forecastday"][1]["pop"];                     DPop2       = String(pop2);
  643.   String w_dir2     = forecast["forecastday"][1]["avewind"]["dir"];          DW_dir2     = String(w_dir2);
  644.   String w_dir_deg2 = forecast["forecastday"][1]["avewind"]["degrees"];      DW_dir_deg2 = String(w_dir_deg2);
  645.   int humi2         = forecast["forecastday"][1]["avehumidity"];             DHumi2      = String(humi2);
  646.   String WDay3      = forecast["forecastday"][2]["date"]["weekday"];         DWDay3      = WDay3;
  647.   int DateDa3       = forecast["forecastday"][2]["date"]["day"];             DDateDa3    = DateDa3<10?"0"+String(DateDa3):String(DateDa3);
  648.   String Mon3       = forecast["forecastday"][2]["date"]["monthname_short"]; DMon3       = Mon3;
  649.   int DateYr3       = forecast["forecastday"][2]["date"]["year"];            DDateYr3    = String(DateYr3).substring(2);
  650.   if (Units == "M" || Units == "X") {
  651.     String icon3         = forecast["forecastday"][2]["icon"];               Dicon3      = String(icon3);
  652.     String conditions3    = forecast["forecastday"][2]["conditions"];        Dconditions3   = String(conditions3);
  653.     int Htemp3        = forecast["forecastday"][2]["high"]["celsius"];       DHtemp3     = String(Htemp3);
  654.     int Ltemp3        = forecast["forecastday"][2]["low"]["celsius"];        DLtemp3     = String(Ltemp3);
  655.     int rain3         = forecast["forecastday"][2]["qpf_allday"]["mm"];      DRain3      = String(rain3)+"mm";
  656.     if (Units == "M") {int w_mph3 = forecast["forecastday"][2]["avewind"]["kph"]; DW_mph3 = String(w_mph3)+"km/h"; }
  657.     else {int w_mph3  = forecast["forecastday"][2]["avewind"]["mph"];        DW_mph3     = String(w_mph3)+"mph"; }
  658.   }
  659.   String icon_url3  = forecast["forecastday"][2]["icon_url"];           
  660.   Dicon_url3        = icon_url3.substring(0,icon_url3.indexOf("/i/c/")+5) + icon_set + icon_url3.substring(icon_url3.indexOf("/i/c/")+6);
  661.   String pop3       = forecast["forecastday"][2]["pop"];                     DPop3       = String(pop3);
  662.   String w_dir3     = forecast["forecastday"][2]["avewind"]["dir"];          DW_dir3     = String(w_dir3);
  663.   String w_dir_deg3 = forecast["forecastday"][2]["avewind"]["degrees"];      DW_dir_deg3 = String(w_dir_deg3);
  664.   int humi3         = forecast["forecastday"][2]["avehumidity"];             DHumi3      = String(humi3);
  665.   String WDay4      = forecast["forecastday"][3]["date"]["weekday"];         DWDay4      = WDay4;
  666.   int DateDa4       = forecast["forecastday"][3]["date"]["day"];             DDateDa4    = DateDa4<10?"0"+String(DateDa4):String(DateDa4);
  667.   String Mon4       = forecast["forecastday"][3]["date"]["monthname_short"]; DMon4       = Mon4;
  668.   int DateYr4       = forecast["forecastday"][3]["date"]["year"];            DDateYr4    = String(DateYr4).substring(2);
  669.   if (Units == "M" || Units == "X") {
  670.     String icon4         = forecast["forecastday"][3]["icon"];               Dicon4      = String(icon4);
  671.     String conditions4    = forecast["forecastday"][3]["conditions"];        Dconditions4   = String(conditions4);
  672.     int Htemp4        = forecast["forecastday"][3]["high"]["celsius"];       DHtemp4     = String(Htemp4);
  673.     int Ltemp4        = forecast["forecastday"][3]["low"]["celsius"];        DLtemp4     = String(Ltemp4);
  674.     int rain4         = forecast["forecastday"][3]["qpf_allday"]["mm"];      DRain4      = String(rain4)+"mm";
  675.     if (Units == "M") {int w_mph4 = forecast["forecastday"][3]["avewind"]["kph"]; DW_mph4 = String(w_mph4)+"km/h";}
  676.     else {int w_mph4  = forecast["forecastday"][3]["avewind"]["mph"];        DW_mph4     = String(w_mph4)+"mph";}
  677.   }
  678.   String icon_url4  = forecast["forecastday"][3]["icon_url"];           
  679.   Dicon_url4        = icon_url4.substring(0,icon_url4.indexOf("/i/c/")+5) + icon_set + icon_url4.substring(icon_url4.indexOf("/i/c/")+6);
  680.   String pop4       = forecast["forecastday"][3]["pop"];                     DPop4       = String(pop4);
  681.   String w_dir4     = forecast["forecastday"][3]["avewind"]["dir"];          DW_dir4     = String(w_dir4);
  682.   String w_dir_deg4 = forecast["forecastday"][3]["avewind"]["degrees"];      DW_dir_deg4 = String(w_dir_deg4);
  683.   int humi4         = forecast["forecastday"][3]["avehumidity"];             DHumi4      = String(humi4);
  684.   JsonObject& current = root["forecast"]["txt_forecast"];      
  685.   String Txw1  = current ["forecastday"][0]["fcttext_metric"];  // Read the text describing the forecast.
  686.   Txw1.toCharArray(Txtweather, 200);                            // Convert String to CharArray for Nextion
  687. return true;
  688. }
  689. bool showWeather_conditions(char *json)
  690. {// Convert forecast received data into Strings and values
  691.   DynamicJsonBuffer jsonBuffer(8704);
  692.   char *jsonstart = strchr(json, '{');
  693. //Serial.println(F("jsonstart ")); Serial.println(jsonstart); // This is input data
  694.   if (jsonstart == NULL) {
  695.     Serial.println(F("JSON data missing"));
  696.     return false; }
  697.   json = jsonstart;
  698.   // Parse JSON
  699.   JsonObject& root = jsonBuffer.parseObject(json);
  700.   if (!root.success()) {
  701.     Serial.println(F("jsonBuffer.parseObject() failed"));
  702.     return false; }
  703.   JsonObject& current = root["current_observation"];
  704.   const float temp_c = current["temp_c"];         // Extract local temp. now
  705.   const float wind_c = current["wind_kph"];       // Extract local wind speed now
  706.   const char  h_c = current["relative_humidity"]; // Extract local humidity now
  707.   temp_e=temp_c+0.5;                              // Round the decimal value                  
  708.   wind_e=String(wind_c,0)+"km/h";                 // Convert wind speed to string
  709.   JsonObject& currentup = root["sun_phase"]["sunrise"];
  710.   String h_u = currentup["hour"];                  // Extract local Sunrise hour
  711.   h_up=String(h_u);
  712.   String m_u = currentup["minute"];                // Extract local Sunrise minute
  713.   m_up=String(m_u);
  714.   JsonObject& currentset = root["sun_phase"]["sunset"];
  715.   String h_s = currentset["hour"];                  // Extract local Sunrise hour
  716.   h_set=String(h_s);
  717.   String m_s = currentset["minute"];                // Extract local Sunrise minute
  718.   m_set=String(m_s);
  719.   return true;                                      // All conversions worked, return True
  720. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 小时前

【Arduino 动手做】ESP32 和 Nextion 的原子钟和天气

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail