Arduino code
The Ardino code below contains some information concerning:
- Choice of the compatible board in the Arduino IDE. If you do not have such boards available under "Tools", then you should insert the following line in File/Preferences/Additional Boards Manager URL:
- Code size, copyright, sources.
The required libraries are:
TimeLib.h
excellent time library by Paul Stoffregen (https://github.com/PaulStoffregen/Time)WiFi.h
WiFiClient.h
WiFiUdp.h for sending requests and receiving server data.
Nextion.h (https://github.com/bborncr/nextion) this is a small, adaptable library, for communication with Nextion
ArduinoJson.h (https://github.com/bblanchon/ArduinoJson) converts the received bytes into separate variables for weather data.
The code has the following steps:
- In Setup it connects to the access point (router) of your home (put your codes in xxxxx and yyyyy). Then it connects to a time server:
"ntps1-0.cs.tu-berlin.de"
, updates time and connects twice by UDP tohttp://www.wunderground.com/weather/
. You will need anAPI_key
, to put instead of zzzzz, which you can get freely fromhttp://www.wunderground.com/weather/api/d/docs
.
Then put your city, country, etc. for weather data. The first call is for the weather forecast:obtain_forecast("forecast"); // Get weather forecast
The second call is for local conditions. Look in the Wundergound site for the nearest meteorologic station to your home. Put its ID in wwwww
to get the correct temperature, wind speed, humidity, sunrise and sunset hours.
obtain_forecast("conditions"); // Get local conditions
Then the WiFi is turned off for an hour, reducing considerably the board required power.
- In Loop, each hour, WiFi is turned on, and all steps done in Setup are repeated. The time values (HH,MM,SS) are sent to Nextion each second. The accumulated time errors during one hour are less than 1s, after which a new adjustment takes place.
When copying the code below, check the long lines for wrong wrapping.
/* Upload this project to GeekWorm ESP32-C1 using :
* -selected board: >>SparkFun ESP32 Thing<< or >> Wemos WiFi& Bluetooth battery<<
* - set it to 40MHz (enough for this project)
* -upload speed: 115200 : IMPORTANT!
* -select available COM port
* Connect USB direct to computer (200 mA required +50 mA for LCD) or external power (5V-350mA min/500 mA better)
* If not enough current available: Brownout error!
* Pins: Geekworm ESP32 <--> Nextion
* IO16 - TX
* IO17 - RX
* GND - GND
* 3.3V - +5v (Nextion works also with 3.3V)
* Use Library: "nextion" with a modified file Nextion.h:
* #define nextion Serial2 // This line is for ESP32 with hardware Serial2
* //#define USE_SOFTWARE_SERIAL //Comment this line if you use HardwareSerial
* The Nextion file is genrated using Nextion Editor: digital_clock-weather.HMI
* Once compiled, the file digital_clock-weather.tft can be transfered from File/Open Build folder to the transfer SD card.
* With the SD card inserted, Nextion updates the screen. Remove the SD card and connect the pins to ESP32.
* Project size: 512910/1310720 bytes (321152 compressed) with variables 47956/294912 bytes
* Receives and displays the weather forecast from the Weather Underground and then displays data using a
* JSON decoder wx data to a NEXTION display.
* Weather data received via WiFi connection from Weather Underground Servers and using their 'Forecast' API and data
* is decoded using Copyright Benoit Blanchon's (c) 2014-2017 excellent JSON library.
* The MIT License (MIT) is copyright (c) 2017 by David Bird and permission is hereby granted, free of charge, to
* any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, but not to sub-license and/or
* to sell copies of the Software or to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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.
* See more at http://dsbird.org.uk
*/
HardwareSerial Serial2(2); // Activate Serial communication 2 on ESP32 (RX=IO16 and TX=IO17)
#include <TimeLib.h> // Arduino Time library for 32 bit
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <Nextion.h> // Was modified to accept Serial1 hardware on ESP32
#include <ArduinoJson.h>
Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port
const char ssid[] = "xxxxxxxxxxx"; // your network SSID (name)
const char pass[] = "yyyyyyyyyyy"; // your network password
const int ledPin =0, timeZone = 2; // East European Time winter time
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
String RomanMonths[12] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"}; // January is month 0
String month_of_year[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; // January is month 0
int days,DST=0;
unsigned long t0=0, interval=3600; // Update interval (s) (1h is ok)
//------ WEATHER NETWORK VARIABLES---------
// Use your own API key by signing up for a free developer account at http://www.wunderground.com/weather/api/
//Selected Plan: Stratus Developer: Calls Per Day= 500; Calls Per Minute : 10
String API_key = "zzzzzzzzzzzz"; // See: http://www.wunderground.com/weather/api/d/docs (change here with your KEY)
String City = "BBBBBBBB"; // Your home city : Weather Station ID: wwwwwwwww
String pws = "PPPPPPPPP";
String Country = "ZZ"; // Your country
String Conditions = "conditions"; // See: http://www.wunderground.com/weather/api/d/docs?d=data/index&MR=1
char wxserver[] = "api.wunderground.com"; // Address for WeatherUnderGround
// unsigned long lastConnectionTime = 0; // Last time you connected to the server, in milliseconds
String SITE_WIDTH = "900";
String icon_set = "k"; //
String Units = "M"; // Default use either M for Metric, X for Mixed and I for Imperial
char* conds[]={"\"temp_c\":"};
float temp_c=0;
int temp_e, count=0;
String wind_e, h_up, m_up, h_set, m_set; //
boolean timeok=false, foreok=false, condok=false; // Update flags
//################ PROGRAM VARIABLES and OBJECTS ################
// Conditions
String webpage, city, country, date_time, observationtime,
DWDay0, DMon0, DDateDa0, DDateMo0, DDateYr0, Dicon0, Dicon_url0, DHtemp0, DLtemp0, DHumi0, Dpop0, DRain0, DW_mph0, DW_dir0, DW_dir_deg0, DWeather0, Dconditions0, DcurrentTemp, Txw1,
DWDay1, DMon1, DDateDa1, DDateMo1, DDateYr1, Dicon1, Dicon_url1, DHtemp1, DLtemp1, DHumi1, DPop1, DRain1, DW_mph1, DW_dir1, DW_dir_deg1, DWeather1, Dconditions1,
DWDay2, DMon2, DDateDa2, DDateMo2, DDateYr2, Dicon2, Dicon_url2, DHtemp2, DLtemp2, DHumi2, DPop2, DRain2, DW_mph2, DW_dir2, DW_dir_deg2, DWeather2, Dconditions2,
DWDay3, DMon3, DDateDa3, DDateMo3, DDateYr3, Dicon3, Dicon_url3, DHtemp3, DLtemp3, DHumi3, DPop3, DRain3, DW_mph3, DW_dir3, DW_dir_deg3, DWeather3, Dconditions3,
DWDay4, DMon4, DDateDa4, DDateMo4, DDateYr4, Dicon4, Dicon_url4, DHtemp4, DLtemp4, DHumi4, DPop4, DRain4, DW_mph4, DW_dir4, DW_dir_deg4, DWeather4, Dconditions4;
char buffer[100] = {0};
char buffer_hour[10] = {0};
char Txtweather[150];
//-------------------------------------------------------------------------------------------
// NTP Servers:
static const char ntpServerName[] = "ntps1-0.cs.tu-berlin.de"; // Chosen Atomic Time server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp; // Initialize User Datagram Protocol (UDP)
unsigned int localPort = 8888; // local port to listen for UDP time packets
// List of the functions defined below:
void callserver();
time_t getNtpTime(); // Convert received seconds into HH:MM:SS, YY-MO-DD
void sendNTPpacket(IPAddress &address); // Require site data
void digitalClockDisplay(); // print time on Nextion
void weatherDisplay(); // print weather on Nextion
void setup()
{
Serial.begin(115200); // USB communication with Serial Monitor
Serial2.begin(9600); // Initiate 2-nd UART towards Nextion
pinMode(ledPin, OUTPUT); // Set Led pin as output
callserver(); // Connect to local server
Serial.print("Synchronizing : ");
Serial.println(ntpServerName);
setSyncProvider(getNtpTime); // Get from Internet the Atomic Clock Time
setSyncInterval(interval); // Resynchronize after 'interval' seconds
obtain_forecast("forecast"); // Get weather forecast
obtain_forecast("conditions"); // Get local conditions
t0 = millis(); // hold moment when weather was displayed
digitalWrite(ledPin, HIGH); // LED OFF if OK
Serial.println("==============================================");
Serial.print("Weather for current time:");
Serial.print(hour());Serial.print(":");Serial.print(minute());Serial.print(":");Serial.println(second());
Serial.print("Time status:");Serial.println(timeok);
Serial.print("Forecast status:");Serial.println(foreok);
Serial.print("Conditions status:");Serial.println(condok);
Serial.println(DWDay1);
Serial.println(Dicon1);
Serial.println(DHtemp1);
Serial.println(DLtemp1);
Serial.println(DHumi1);
Serial.println(DW_mph1);
Serial.println(DWDay2);
Serial.println(Dicon2);
Serial.println(DHtemp2);
Serial.println(DLtemp2);
Serial.println(DHumi2);
Serial.println(DW_mph2);
Serial.println(DWDay3);
Serial.println(Dicon3);
Serial.println(DHtemp3);
Serial.println(DLtemp3);
Serial.println(DHumi3);
Serial.println(DW_mph3);
Serial.println("--Local weather, now: --");
Serial.println(Txtweather);
Serial.println(temp_e);
Serial.println(wind_e);
Serial.print(h_up);Serial.print(":"); Serial.println(m_up);
Serial.print(h_set);Serial.print(":");Serial.println(m_set);
Serial.println("==============================================");
digitalClockDisplay(); // Send clock data to Nextion
weatherDisplay(); // Send weather data to Nextion
count=1;
Serial.printf("WiFi off for %g\n",interval);
WiFi.disconnect(true);
}
time_t prevDisplay = 0; // moment when the clock was displayed
void loop()
{
// Every second update time on Nextion
if (now() != prevDisplay) { // ..update the display only if time has changed =every sec.
prevDisplay = now();
//----------------------------------------
// Compute DST if server not providing this
if (month()>3 && month()<10)
DST=1;
days=31-((5*year())/4+4)%7;
if (month()==3 && day()>=days)
DST=1;
days=31-((5*year())/4+1)%7;
if (month()==10 && day()<days)
DST=1;
//----------------------------------------
digitalClockDisplay(); // Send clock data to Nextion
}
// Every interval of time, connect to server and update time and weather
if(millis() - t0 > interval*1000) // after every time "interval"
{
callserver(); // Connect to local server
Serial.print("Synchronizing : ");
Serial.println(ntpServerName);
setSyncProvider(getNtpTime); // Get from Internet the Atomic Clock Time
delay(10);
obtain_forecast("forecast"); // Get weather forecast
delay(10);
obtain_forecast("conditions"); // Get local conditions
// Just for debugging, print results on Serial Monitor attached via USB
Serial.println("==============================================");
Serial.print("Weather for current time:");
Serial.print(hour());Serial.print(":");Serial.print(minute());Serial.print(":");Serial.println(second());
count++;
Serial.print("Update no:");Serial.println(count);
Serial.print("Time status:");Serial.println(timeok);
Serial.print("Forecast status:");Serial.println(foreok);
Serial.print("Conditions status:");Serial.println(condok);
Serial.println(DWDay1);
Serial.println(Dicon1);
Serial.println(DHtemp1);
Serial.println(DLtemp1);
Serial.println(DHumi1);
Serial.println(DW_mph1);
Serial.println(DWDay2);
Serial.println(Dicon2);
Serial.println(DHtemp2);
Serial.println(DLtemp2);
Serial.println(DHumi2);
Serial.println(DW_mph2);
Serial.println(DWDay3);
Serial.println(Dicon3);
Serial.println(DHtemp3);
Serial.println(DLtemp3);
Serial.println(DHumi3);
Serial.println(DW_mph1);
Serial.println(Txtweather);
Serial.println(temp_e);
Serial.println(wind_e);
Serial.print(h_up);Serial.print(":"); Serial.println(m_up);
Serial.print(h_set);Serial.print(":");Serial.println(m_set);
Serial.printf("WiFi off for %g\n",interval);
weatherDisplay(); // Send weather data to Nextion
t0= millis(); // Mark this moment.
//setSyncInterval(interval); // Resynchronize time after 'interval' seconds
WiFi.disconnect(true);
}
}
// =======================================================================
void callserver(){
// We start by connecting to a WiFi network
Serial.println("----------------------");
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
Serial.println("----");
Serial.print("Connecting...");
while (WiFi.status() != WL_CONNECTED) {
// LED blink as long as the connection is not establihed
delay(250);
digitalWrite(ledPin, LOW);
delay(250);
digitalWrite(ledPin, HIGH);
Serial.print(".");
}
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("----------------------");
// At this stage the ESP32 is connected to the local network
// Prepare also UDP connection for data download:
Serial.println("Starting UDP");
Udp.begin(localPort); // Start User Datagram Protocol (UDP) on localPort
}
void digitalClockDisplay()
{// Write Clock data on Nextion
// Display the time. Digital clock.
// Send a number to a number cell of Nextion
myNextion.setComponentValue("n0",hour());
myNextion.setComponentValue("n1",minute());
myNextion.setComponentValue("n2",second());
myNextion.setComponentText("t3",daysOfTheWeek[weekday()-1]);
// Send strings to string cells of Nextion
myNextion.setComponentText("t4", String(day()));
//myNextion.setComponentText("t5", String(month()));
myNextion.setComponentText("t5", RomanMonths[month()-1]);
myNextion.setComponentText("t6", String(year()));
}
void weatherDisplay()
{// Write weather data on Nextion
myNextion.sendCommand("page 0");
myNextion.setComponentValue("n3",temp_e); // to numeric obj. n3 Temp. outside now
myNextion.setComponentText("t8",wind_e); // to text obj. 8 Wind speed outside now
myNextion.setComponentText("t10",DHtemp1); // to text obj. 10 Max Temp. of the day
myNextion.setComponentText("t11",DLtemp1); // to text obj. 11 Min Temp. of the day
myNextion.setComponentText("t12",DHumi1); // to text obj. 12 Humidity of the day
myNextion.setComponentText("g0",Txtweather); // Scroll weather description text !
myNextion.setComponentText("t33",h_up+":"+m_up); // to text obj. 33 Sun rise time
myNextion.setComponentText("t34",h_set+":"+m_set); // to text obj. 33 Sun set time
myNextion.sendCommand("page 1");
myNextion.setComponentText("t14",daysOfTheWeek[(weekday())%7]); // Swow tomorow
myNextion.setComponentText("t20",DHtemp2); //to text obj. 20 Estimated High Temp.
myNextion.setComponentText("t21",DLtemp2); // Estimated Low Temp.
myNextion.setComponentText("t22",DHumi2); // Estimated humidity
myNextion.setComponentText("t31",DW_mph2); // Estimated wind speed
myNextion.setComponentText("t15",daysOfTheWeek[(weekday()+1)%7]); // Swow after tomorow
myNextion.setComponentText("t26",DHtemp3); //to text obj. 26 Estimated High Temp.
myNextion.setComponentText("t27",DLtemp3); // Estimated Low Temp.
myNextion.setComponentText("t28",DHumi3); // Estimated humidity
myNextion.setComponentText("t32",DW_mph3); // Estimated wind speed
myNextion.sendCommand("page 0");
// Now change the pictures accordingly:
if(Dicon1=="clear")
myNextion.sendCommand("p0.pic=0");
if(Dicon1=="partlycloudy")
myNextion.sendCommand("p0.pic=1");
if(Dicon1=="cloudy")
myNextion.sendCommand("p0.pic=2");
if(Dicon1=="rain" || Dicon1=="chancerain")
myNextion.sendCommand("p0.pic=3");
if(Dicon1=="snow")
myNextion.sendCommand("p1.pic=4");
myNextion.sendCommand("page 1"); // Go to page 1
if(Dicon2=="clear")
myNextion.sendCommand("p1.pic=0");
if(Dicon2=="partlycloudy")
myNextion.sendCommand("p1.pic=1");
if(Dicon2=="cloudy")
myNextion.sendCommand("p1.pic=2");
if(Dicon2=="rain" || Dicon2=="chancerain")
myNextion.sendCommand("p1.pic=3");
if(Dicon2=="snow")
myNextion.sendCommand("p1.pic=4");
if(Dicon3=="clear")
myNextion.sendCommand("p2.pic=0");
if(Dicon3=="partlycloudy")
myNextion.sendCommand("p2.pic=1");
if(Dicon3=="cloudy")
myNextion.sendCommand("p2.pic=2");
if(Dicon3=="rain" || Dicon3=="chancerain")
myNextion.sendCommand("p2.pic=3");
if(Dicon3=="snow")
myNextion.sendCommand("p2.pic=4");
myNextion.sendCommand("page 0"); // Come back to page 0
if (condok)
myNextion.setComponentValue("bt1",1); // Button1 is green if local conditions are updated ...
else
myNextion.setComponentValue("bt1",0); // else it is red.
if (foreok)
myNextion.setComponentValue("bt2",1); // Button2 is green if forecast is updated ...
else
myNextion.setComponentValue("bt2",0); // else it is red.
}
/*-------- NTP code ----------*/
time_t getNtpTime()
{
Udp.begin(localPort);
IPAddress ntpServerIP; // NTP server's ip address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request to:");
WiFi.hostByName(ntpServerName, ntpServerIP);
Serial.print(ntpServerName);
Serial.print("= ");
Serial.println(ntpServerIP);
delay(500);
sendNTPpacket(ntpServerIP);
unsigned long beginWait = millis();
while (millis() - beginWait < 2500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
Serial.println("Received NTP Response. Updating Time.");
Serial.println("=====================================");
timeok=true;
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR+1; // maybe add +1 for update delays?
}
}
Serial.println("No NTP Response :-(");
Serial.println("Time is not synchronized");
timeok=false;
return 0; // return 0 if unable to get the time
}
void sendNTPpacket(IPAddress& address)
// send an NTP request to the time server at the given address
{
Serial.println("sending NTP packet...");
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
void obtain_forecast (String forecast_type) {
static char RxBuf[8704];
String request;
if (forecast_type=="forecast")
request = "GET /api/" + API_key + "/"+ forecast_type + "/q/" + Country + "/" + City + ".json HTTP/1.1\r\n"; // Request Country/City
else
request = "GET /api/" + API_key + "/"+ forecast_type + "/astronomy/q/geolookup/pws:" + pws + ".json HTTP/1.1\r\n"; // Request data by pws station
// http://api.wunderground.com/api/7a4e220afaaf6547/conditions/q/geolookup/pws:IBUCURET77.json
request += F("User-Agent: Weather Webserver v");
//request += version;
request += F("\r\n");
request += F("Accept: */*\r\n");
request += "Host: " + String(wxserver) + "\r\n";
request += F("Connection: close\r\n");
request += F("\r\n");
//Serial.println(request);
Serial.print(F("Connecting to ")); Serial.println(wxserver);
WiFiClient httpclient;
if (!httpclient.connect(wxserver, 80)) {
Serial.println(F("connection failed"));
foreok=false;
condok=false;
httpclient.flush(); //Waits until all outgoing characters in buffer have been sent (forever if lost connection!)
httpclient.stop();
return;
}
Serial.print("Sending to Weather server:"); Serial.println(request);
httpclient.print(request); //send the request to the server
httpclient.flush(); //Waits until all outgoing characters in buffer have been sent (forever if connection lost)
Serial.println("The request was sent. Waiting for the response...");
// Collect http response headers and content from Weather Underground, discarding HTTP headers, the content is JSON formatted and will be returned in RxBuf.
int respLen = 0;
bool skip_headers = true;
String rx_line;
unsigned long beginWait = millis();
while ((httpclient.connected() || httpclient.available()) && (millis() - beginWait < 10000)) {
if (skip_headers) {
rx_line = httpclient.readStringUntil('\n'); Serial.println(rx_line);
if (rx_line.length() <= 1) { // a blank line denotes end of headers
skip_headers = false;
}
}
else {
int bytesIn;
bytesIn = httpclient.read((uint8_t *)&RxBuf[respLen], sizeof(RxBuf) - respLen);
//Serial.print(F("bytesIn ")); Serial.println(bytesIn);
if (bytesIn > 0) {
respLen += bytesIn;
if (respLen > sizeof(RxBuf)) respLen = sizeof(RxBuf);
}
else if (bytesIn < 0) {
Serial.print("?"); // Appears very often, waiting for an answer!
}
}
delay(100);
}
httpclient.stop();
RxBuf[respLen++] = '\0'; // Terminate the C string
// RxBuf contains now the server response, of length=respLen.
Serial.println("");Serial.print(F("respLen= ")); Serial.println(respLen);
if (respLen<=1 && forecast_type == "forecast"){
foreok=false; // If no data available return without changing forecast
return;
}
if (respLen<=1 && forecast_type == "conditions"){
condok=false; // If no data available return without changing conditions
return;
}
if (forecast_type == "forecast"){
if (showWeather_forecast(RxBuf)){
delay(1000);
}
}
if (forecast_type == "conditions"){
if (showWeather_conditions(RxBuf)){
delay(1000);
}
}
}
bool showWeather_forecast(char *json)
{// Convert forecast received data into Strings and values
DynamicJsonBuffer jsonBuffer(8704);
char *jsonstart = strchr(json, '{'); // Look for first "{"
// Serial.println(F("jsonstart ")); Serial.println(jsonstart); // This is input data
if (jsonstart == NULL) {
Serial.println(F("JSON data missing"));
foreok=false;
return false;
}
json = jsonstart;
// Parse JSON
JsonObject& root = jsonBuffer.parseObject(json);
if (!root.success()) {
Serial.println(F("jsonBuffer.parseObject() failed"));
foreok=false;
return false;
}
JsonObject& forecast = root["forecast"]["simpleforecast"];
String WDay1 = forecast["forecastday"][0]["date"]["weekday"]; DWDay1 = WDay1;
int DateDa1 = forecast["forecastday"][0]["date"]["day"]; DDateDa1 = DateDa1<10?"0"+String(DateDa1):String(DateDa1);
String Temp_mon = forecast["forecastday"][0]["date"]["monthname"];
String Mon1 = forecast["forecastday"][0]["date"]["monthname_short"]; DMon1 = Mon1;
int DateYr1 = forecast["forecastday"][0]["date"]["year"]; DDateYr1 = String(DateYr1).substring(2);
observationtime = "from " + String(DDateDa1) + " " + Temp_mon + ", " + DateYr1;
if (Units == "M" || Units == "X") {
String icon1 = forecast["forecastday"][0]["icon"]; Dicon1 = String(icon1);
String conditions1 = forecast["forecastday"][0]["conditions"]; Dconditions1 = String(conditions1);
int Htemp1 = forecast["forecastday"][0]["high"]["celsius"]; DHtemp1 = String(Htemp1);
int Ltemp1 = forecast["forecastday"][0]["low"]["celsius"]; DLtemp1 = String(Ltemp1);
int rain1 = forecast["forecastday"][0]["qpf_allday"]["mm"]; DRain1 = String(rain1)+"mm";
if (Units == "M") {int w_mph1 = forecast["forecastday"][0]["avewind"]["kph"]; DW_mph1 = String(w_mph1)+"km/h";}
else {int w_mph1 = forecast["forecastday"][0]["avewind"]["mph"]; DW_mph1 = String(w_mph1)+"mph";}
}
String icon_url1 = forecast["forecastday"][0]["icon_url"];
Dicon_url1 = icon_url1.substring(0,icon_url1.indexOf("/i/c/")+5) + icon_set + icon_url1.substring(icon_url1.indexOf("/i/c/")+6);
String pop1 = forecast["forecastday"][0]["pop"]; DPop1 = String(pop1);
String w_dir1 = forecast["forecastday"][0]["avewind"]["dir"]; DW_dir1 = String(w_dir1);
String w_dir_deg1 = forecast["forecastday"][0]["avewind"]["degrees"]; DW_dir_deg1 = String(w_dir_deg1);
int humi1 = forecast["forecastday"][0]["avehumidity"]; DHumi1 = String(humi1);
String WDay2 = forecast["forecastday"][1]["date"]["weekday"]; DWDay2 = WDay2;
int DateDa2 = forecast["forecastday"][1]["date"]["day"]; DDateDa2 = DateDa2<10?"0"+String(DateDa2):String(DateDa2);
String Mon2 = forecast["forecastday"][1]["date"]["monthname_short"]; DMon2 = Mon2;
int DateYr2 = forecast["forecastday"][1]["date"]["year"]; DDateYr2 = String(DateYr2).substring(2);
if (Units == "M" || Units == "X") {
String icon2 = forecast["forecastday"][1]["icon"]; Dicon2 = String(icon2);
String conditions2 = forecast["forecastday"][1]["conditions"]; Dconditions2 = String(conditions2);
int Htemp2 = forecast["forecastday"][1]["high"]["celsius"]; DHtemp2 = String(Htemp2);
int Ltemp2 = forecast["forecastday"][1]["low"]["celsius"]; DLtemp2 = String(Ltemp2);
int rain2 = forecast["forecastday"][1]["qpf_allday"]["mm"]; DRain2 = String(rain2)+"mm";
if (Units == "M"){int w_mph2 = forecast["forecastday"][1]["avewind"]["kph"]; DW_mph2 = String(w_mph2)+"km/h";}
else {int w_mph2 = forecast["forecastday"][1]["avewind"]["mph"]; DW_mph2 = String(w_mph2)+"mph";
}
}
String icon_url2 = forecast["forecastday"][1]["icon_url"];
Dicon_url2 = icon_url2.substring(0,icon_url2.indexOf("/i/c/")+5) + icon_set + icon_url2.substring(icon_url2.indexOf("/i/c/")+6);
String pop2 = forecast["forecastday"][1]["pop"]; DPop2 = String(pop2);
String w_dir2 = forecast["forecastday"][1]["avewind"]["dir"]; DW_dir2 = String(w_dir2);
String w_dir_deg2 = forecast["forecastday"][1]["avewind"]["degrees"]; DW_dir_deg2 = String(w_dir_deg2);
int humi2 = forecast["forecastday"][1]["avehumidity"]; DHumi2 = String(humi2);
String WDay3 = forecast["forecastday"][2]["date"]["weekday"]; DWDay3 = WDay3;
int DateDa3 = forecast["forecastday"][2]["date"]["day"]; DDateDa3 = DateDa3<10?"0"+String(DateDa3):String(DateDa3);
String Mon3 = forecast["forecastday"][2]["date"]["monthname_short"]; DMon3 = Mon3;
int DateYr3 = forecast["forecastday"][2]["date"]["year"]; DDateYr3 = String(DateYr3).substring(2);
if (Units == "M" || Units == "X") {
String icon3 = forecast["forecastday"][2]["icon"]; Dicon3 = String(icon3);
String conditions3 = forecast["forecastday"][2]["conditions"]; Dconditions3 = String(conditions3);
int Htemp3 = forecast["forecastday"][2]["high"]["celsius"]; DHtemp3 = String(Htemp3);
int Ltemp3 = forecast["forecastday"][2]["low"]["celsius"]; DLtemp3 = String(Ltemp3);
int rain3 = forecast["forecastday"][2]["qpf_allday"]["mm"]; DRain3 = String(rain3)+"mm";
if (Units == "M") {int w_mph3 = forecast["forecastday"][2]["avewind"]["kph"]; DW_mph3 = String(w_mph3)+"km/h"; }
else {int w_mph3 = forecast["forecastday"][2]["avewind"]["mph"]; DW_mph3 = String(w_mph3)+"mph"; }
}
String icon_url3 = forecast["forecastday"][2]["icon_url"];
Dicon_url3 = icon_url3.substring(0,icon_url3.indexOf("/i/c/")+5) + icon_set + icon_url3.substring(icon_url3.indexOf("/i/c/")+6);
String pop3 = forecast["forecastday"][2]["pop"]; DPop3 = String(pop3);
String w_dir3 = forecast["forecastday"][2]["avewind"]["dir"]; DW_dir3 = String(w_dir3);
String w_dir_deg3 = forecast["forecastday"][2]["avewind"]["degrees"]; DW_dir_deg3 = String(w_dir_deg3);
int humi3 = forecast["forecastday"][2]["avehumidity"]; DHumi3 = String(humi3);
String WDay4 = forecast["forecastday"][3]["date"]["weekday"]; DWDay4 = WDay4;
int DateDa4 = forecast["forecastday"][3]["date"]["day"]; DDateDa4 = DateDa4<10?"0"+String(DateDa4):String(DateDa4);
String Mon4 = forecast["forecastday"][3]["date"]["monthname_short"]; DMon4 = Mon4;
int DateYr4 = forecast["forecastday"][3]["date"]["year"]; DDateYr4 = String(DateYr4).substring(2);
if (Units == "M" || Units == "X") {
String icon4 = forecast["forecastday"][3]["icon"]; Dicon4 = String(icon4);
String conditions4 = forecast["forecastday"][3]["conditions"]; Dconditions4 = String(conditions4);
int Htemp4 = forecast["forecastday"][3]["high"]["celsius"]; DHtemp4 = String(Htemp4);
int Ltemp4 = forecast["forecastday"][3]["low"]["celsius"]; DLtemp4 = String(Ltemp4);
int rain4 = forecast["forecastday"][3]["qpf_allday"]["mm"]; DRain4 = String(rain4)+"mm";
if (Units == "M") {int w_mph4 = forecast["forecastday"][3]["avewind"]["kph"]; DW_mph4 = String(w_mph4)+"km/h";}
else {int w_mph4 = forecast["forecastday"][3]["avewind"]["mph"]; DW_mph4 = String(w_mph4)+"mph";}
}
String icon_url4 = forecast["forecastday"][3]["icon_url"];
Dicon_url4 = icon_url4.substring(0,icon_url4.indexOf("/i/c/")+5) + icon_set + icon_url4.substring(icon_url4.indexOf("/i/c/")+6);
String pop4 = forecast["forecastday"][3]["pop"]; DPop4 = String(pop4);
String w_dir4 = forecast["forecastday"][3]["avewind"]["dir"]; DW_dir4 = String(w_dir4);
String w_dir_deg4 = forecast["forecastday"][3]["avewind"]["degrees"]; DW_dir_deg4 = String(w_dir_deg4);
int humi4 = forecast["forecastday"][3]["avehumidity"]; DHumi4 = String(humi4);
JsonObject& current = root["forecast"]["txt_forecast"];
String Txw1 = current ["forecastday"][0]["fcttext_metric"]; // Read the text describing the forecast.
Txw1.toCharArray(Txtweather, 150); // Convert String to CharArray for Nextion
foreok=true;
return true;
}
bool showWeather_conditions(char *json)
{// Convert forecast received data into Strings and values
DynamicJsonBuffer jsonBuffer(8704);
char *jsonstart = strchr(json, '{');
//Serial.println(F("jsonstart ")); Serial.println(jsonstart); // This is input data
if (jsonstart == NULL) {
Serial.println(F("JSON data missing"));
condok=false;
return false; }
json = jsonstart;
// Parse JSON
JsonObject& root = jsonBuffer.parseObject(json);
if (!root.success()) {
Serial.println(F("jsonBuffer.parseObject() failed"));
condok=false;
return false; }
JsonObject& current = root["current_observation"];
const float temp_c = current["temp_c"]; // Extract local temp. now
const float wind_c = current["wind_kph"]; // Extract local wind speed now
const char h_c = current["relative_humidity"]; // Extract local humidity now
temp_e=temp_c+0.5; // Round the decimal value
wind_e=String(wind_c,0)+"km/h"; // Convert wind speed to string
JsonObject& currentup = root["sun_phase"]["sunrise"];
String h_u = currentup["hour"]; // Extract local Sunrise hour
h_up=String(h_u);
String m_u = currentup["minute"]; // Extract local Sunrise minute
m_up=String(m_u);
JsonObject& currentset = root["sun_phase"]["sunset"];
String h_s = currentset["hour"]; // Extract local Sunrise hour
h_set=String(h_s);
String m_s = currentset["minute"]; // Extract local Sunrise minute
m_set=String(m_s);
condok=true;
return true; // All conversions worked, return True
}