This is a rather large bit of code. The newest is a reset at 1AM. The reset is when my current issue started.
For this I added the function:
void(* resetFunc) (void) = 0; //declare reset function @ address 0
and in the loop is the bit of code
if (GetTmloint == 1)
{
if (oldReset == 1)
{
Serial.print(GetTmloint);
Serial.println(" Reset Hour **************************");
resetFunc();
}
}
The full code below
/*Web client, WiFi, SD & RA8875
This sketch connects to several websites api.openweathermap.org, local a local InfluxDB and also currently a MySQL DB via PHP
using a WiFi shield and then displays the data on images from the flash chip.
This example is written for a network using WPA encryption. For
WEP or WPA, change the WiFi.begin() call accordingly.
Circuit:
Adafruit Feather M4 Express - Featuring ATSAMD51 - ATSAMD51 Cortex M4
Product ID: 3857
Adafruit AirLift FeatherWing – ESP32 WiFi Co-Processor
Product ID: 4264
RA8875 Driver Board for 40-pin TFT Touch Displays - 800x480 Max
PRODUCT ID: 1590
7.0" 40-pin TFT Display - 800x480 with Touchscreen
Product ID: 2354
DS3231 Precision RTC FeatherWing - RTC Add-on For Feather Boards
PRODUCT ID: 3028
2023-07-15 add restart time to serial monitor
2023-07-13 Hour is not advancing for reset
2023-07-12 adding daily resets
2023-05-04 Disabled waiting for serial connection
2022-05-21 possible fix for "unable to connect" discover with WiFi.disconnect(); and try again
2022-05-19 Getting occasional "unable to connect" errors trying to connect to server: api.openweathermap.org - Possible fix
2022-04-12 the 2020-03-14 Version touch worked and 2020-03-15 Version touch stopped working
2022-04-12 0xF7 looks to be the built in font degree symbol
2022-04-09 Touch Screen is not registering touches
2022-04-09 Sunrise/Sunset and Forcast are only updated every 10 minutes, 144 Times a day
2022-04-07 Forcast Temp03 & Temp04 have not been converted - Issue Fixed
2022-04-07 WindChill issue seems to be noticed when Wind Speed is 0? - issue Fixed
2022-04-01 WindChill was showing higher than actual temperature Added ( ) around elements
2022-03-27 Switching forcast Open Weather Maps OneCall API for Forecasts and posibly Sunrise,Sunset
2022-03-14 changed php path from http://ip/php-demo/index1.php to http://ip/index1.php
2022-03-13 Changed color from Blue background Black squares to Dark Turquoise background & medium Turquoise Squares.
Also added Heat Index, Windchill and Dew point. Also set RTC to UTC time so CST and CDT worked correctly
2022-03-06 Move the Temprature over if it is a 3 digit temperature
2022-03-03 through Docker container PHP-Apache script able to pull Local InfluxDB into display
2022-02-26 Switch to HKS562 the mysql DB has bad data so is not needed
2022-01-06 redraw box for Sunrise Sunset when data is updated to ensure old data is not visable.
2022-01-02 Extract Sunrise and Sunset and able to print it, but it is not converting to local time correctly - Issue fixed
2022-01-01 Adjust Forcast Formating for Temp
2021-12-31 convertToTime and stringUtcToLocal Are able toconvert Forecast JSON UTC DateTime to local DateTime
2021-12-29 convertToTime function may work for strptime. Have it partially working able to convert to DateTime then time_t. Able then call myTZ.toLocal to convert from utc to local TimeZone.
need to find where date info is at and convert some of the steps to a function. - Issue Fixed
2021-12-27 strptime does not seem to be available for parsing to a time_t - Issue Solution Found (ConvertToTime & stringUtcToLocal)
2021-12-22 getWeatherForecast parsing issue was a JSON buffer size issue json buffer 24000 can pull 24 3Hour data sets. Next parse to find Max/min temp,wind,humidity and other data point - Issue Fixed
2021-12-21 Added getWeatherForecast it is having a JSON parseing issue Also added Sunrise-Sunset function time_t is not working correctly although this could be a parseing issue also - Issue Forecast fixed - Issue Sunrise/Set not working Partially Fixed
2021-12-18 Unable to pull influxdb data from: http://10.197.1.57:8086/query?db=Garden&q=SELECT%20*%20FROM%20%22Station%22%20WHERE%20station%20=%2092%20ORDER%20BY%20DESC%20LIMIT%201 - Issue
2021-12-05 currently not woring with builtin data storage BMP header has an issue - Issue
2021-12-04 Rebuilding display finding what works and what does not for the M4.
2021-11-01 using code from older display to use new data sources and M4 feather its builtin Flash, ESP32 WiFi Coprocessor, and a more accurate RTC.
FUNCTIONS Manifest:
void setup() - Starts and sets up the hardware and varibles
void loop() - Main Loop
void printWifiStatus() - Print WiFi status after startup
void guiOff() - based on what the PIR sensor sees disables the display
void guiOn() - based on what the PIR sensor sees enables the display
time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss) - Not yet used
time_t convertToTime(String calTimestamp) - String Formated Time and Converts to time_t called by stringUtcToLocal
time_t stringUtcToLocal(String FCTime) - String Formated Time and Converts to Local time_t
char * makeDateString(time_t t, char *ds) - Formats Date String
char * makeJustDateString(time_t t, char *ds) - Formats Date String
char * makeAltDateString(time_t t, char *ds) - Formats Date String
char * makeDayString(time_t t, char *ds) - Formats Date String
char * makeWeekDayString(time_t t, char *ds) - Formats Date String
char * makeTimeString(time_t t, char *ds) - Formats Date String
char * makeHrMinTimeString(time_t t, char *ds) - Formats Date String
void mainGui() - Main GUI display Function
void checkWiFi() - Checks WiFi Status
void bmpDraw(const char *filename, int x, int y) - Draw Background Image
uint16_t read16(File f) - called by bmpDraw
uint32_t read32(File f) - called by bmpDraw
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) - called by bmpDraw
byte decToBcd(byte val) - called by bmpDraw
void SIRtouch() - Touch Screen Routine
void getLocalDataQuery() - Get local InfluxDB Weather Data
void ShowMaxMin(int xcnt, float tmax, float tmin) - Not currently Used
void getWeatherforcast() - Get Weather 3hr Forcast data
void getSunriseSunset() - Get Sunrise - Sunset data from Forcast site
double heatIndex(double tempF, double Humidity) - Calculate Heat Index from Temperature in F and Humidity
*/
#include<avr/dtostrf.h>
#include <Timezone.h>
#include <TimeLib.h>
#include <ArduinoJson.h> //code is for version 5.xx
#include <SPI.h>
//#include <WiFi101.h>
#include <WiFiNINA.h>
#include <Adafruit_GFX.h>
#include <Adafruit_RA8875.h>
//#include <Fonts/FreeSansBold12pt7b.h>
//#include <Fonts/FreeSansBold24pt7b.h>
//#include <SD.h>
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include <Wire.h>
#include <RTClib.h>
//#include "moonphases.h" //moon phase icons
//Timezone info for Timezone.h
time_t central, utc, curentTime;
// US Eastern Time Zone (Chicago, St Louis)
//TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240}; // Daylight time = UTC - 4 hours
//TimeChangeRule mySTD = {"EST", First, Sun, Nov, 2, -300}; // Standard time = UTC - 5 hours
TimeChangeRule myDST = {"CDT", Second, Sun, Mar, 2, -300}; // Daylight time = UTC - 5 hours
TimeChangeRule mySTD = {"CST", First, Sun, Nov, 2, -360}; // Standard time = UTC - 6 hours
//TimeChangeRule myDST = {"MDT", Second, Sun, Mar, 2, -360}; // Daylight time = UTC - 6 hours
//TimeChangeRule mySTD = {"MST", First, Sun, Nov, 2, -420}; // Standard time = UTC - 7 hours
//TimeChangeRule myDST = {"PDT", Second, Sun, Mar, 2, -420}; // Daylight time = UTC - 7 hours
//TimeChangeRule mySTD = {"PST", First, Sun, Nov, 2, -480}; // Standard time = UTC - 8 hours
Timezone myTZ(myDST, mySTD);
TimeChangeRule *tcr; // pointer to the time change rule, use to get TZ abbrev
char DtTme[20];
int oldReset;
DateTime GetTm;
DateTime GetBoot;
time_t GetBootutc;
time_t GetBootlocal;
time_t GetTmutc;
char GetBootut[20];
time_t GetTmlocal;
char GetTmlo[3];
char GetBootlo[20];
String GetTmloStr;
int GetTmloint;
//Ideally this should be set by above - Work in progress
const int GMT = -5; //change this to adapt it to your time zone
//RTC
//RTC_PCF8523 rtc;
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
char filename[15];
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
#else
#if (SPI_INTERFACES_COUNT == 1 || defined(ADAFRUIT_CIRCUITPLAYGROUND_M0))
Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
#else
Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
#endif
#endif
Adafruit_SPIFlash flash(&flashTransport);
// file system object from SdFat
FatFileSystem fatfs;
// Pin mapping
//
// Set on the ability to turn the display on and off
int inPin = 15; //Defines Feather M0/4 Pin A1/15 as inpin for toggling the display on and off
int dspon = 0;
int dsponbefore = 0;
int mark_time;
// change this to match your SD shield or module;
// Adafruit SD shields and modules: pin 10
//Not needed with new Proc otherwise will change
//const int chipSelect = 10;
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
// Configure the pins used for the ESP32 connection
#define SPIWIFI SPI // The SPI port
#define SPIWIFI_SS 13 // Chip select pin
#define ESP32_RESETN 12 // Reset pin
#define SPIWIFI_ACK 11 // a.k.a BUSY or READY pin
#define ESP32_GPIO0 10
// Library only supports hardware SPI at this time
// Connect SCLK to UNO Digital #13 (Hardware SPI clock)
// Connect MISO to UNO Digital #12 (Hardware SPI MISO)
// Connect MOSI to UNO Digital #11 (Hardware SPI MOSI)
#define RA8875_INT 5
#define RA8875_CS 9
#define RA8875_RESET 6
#define BUFFPIXEL 20
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define BROWN 0x51E5
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define DRKTURQUOISE 0x1B4C
#define MEDTURQUOISE 0x2450
Adafruit_RA8875 tft = Adafruit_RA8875(RA8875_CS, RA8875_RESET);
tsPoint_t _tsLCDPoints[3];
tsPoint_t _tsTSPoints[3];
tsMatrix_t _tsMatrix;
uint16_t tx, ty;
uint16_t x, y;
// This is calibration data for the raw touch data to the screen coordinates
//larger max shrinks dot spread and smaller max increases dot spread
#define TS_MINX 44
#define TS_MINY 130
#define TS_MAXX 775
#define TS_MAXY 510
long lastDebounceTime = 0;
long debounceDelay = 500;
//set GUI display
char GuidisplayState[] = "M1"; //M1 = main GUI screen - Copied to Test
uint32_t currentMillis; // store the current value from millis()
uint32_t previousMillis; // for comparison with currentMillis
uint32_t samplingInterval; // Frenquency to update display in MilliSeconds (millis)
uint32_t currentMillis1; // store the current value from millis()
uint32_t previousMillis1; // for comparison with currentMillis
uint32_t samplingInterval1; // Frenquency to update display in MilliSeconds (millis)
uint16_t displayChange; // Does the display need to be changed 0 = No 1 = Yes
// open weather map
String apiKey = SECRET_APIKEY; // open weather map data source API Key
String location= "4281730"; //the city you want the weather for ?q=cityname
//String location = "4272788"; // The city ID you want the weather from json list ?id=citynumber
char server[] = "api.openweathermap.org";
// open the Local Weather Data
char server1[] = "10.197.1.100";
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP & port 443 is default for HTTPS):
WiFiClient client;
//WiFiSSLClient client;
//Open Weather Map Query
//Find lat lon for weather data site
//http ://api.openweathermap.org/geo/1.0/direct?q=Haysville,KS,US&limit=10&appid=4e8bda75d9c60964...
//Forecast query
//https ://api.openweathermap.org/data/2.5/onecall?lat=37.5644615&lon=-97.3522675&units=imperial&exclude=minutely,hourly,alerts&appid=4e8bda75d9c60964...
//[{"name":"Haysville","lat":37.5644615,"lon":-97.3522675,"country":"US","state":"Kansas"}]
// INFLUXDB Query
//http ://10.197.1.57:8086/query?db=Garden&q=SELECT * FROM "Station" WHERE station = 92 ORDER BY DESC LIMIT 1 //index1.php
//http ://10.197.1.57:8086/query?db=Garden&q=SELECT MEAN("windspeed") FROM "Station" WHERE station = 92 and time > now() - 10m //WindAvg.php
//http ://10.197.1.57:8086/query?db=Garden&q=SELECT MAX("windspeed") FROM "Station" WHERE station = 92 and time > now() - 60m //WindMax.php
void(* resetFunc) (void) = 0; //declare reset function @ address 0
/* Example Command to call reset function
resetFunc();
*/
void setup() {
//-----------------------------------------------------------------------------------------------------------setup
//Initialize serial and wait for port to open:
Serial.begin(9600);
/*
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
*/
//Configure pins for Adafruit ESP32 WiFi CoProcessor
WiFi.setPins(SPIWIFI_SS, SPIWIFI_ACK, ESP32_RESETN, ESP32_GPIO0, &SPIWIFI);
//Configure pins for Adafruit ATWINC1500 Breakout
//WiFi.setPins(11, 13, 12);
//Displays current file path when compiled
Serial.println(__FILE__);
display_Running_Sketch();
//***************RTC Start*******************
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
//For RTC_PCF8523
/*if (! rtc.initialized()) {
Serial.println("RTC is NOT running!");
}*/
//setup reset
//This is my brute force to prevent loss of connection to Open Weather Map
//I have not been able to detect loss of connection and then restart the network connection
//Other than by reboot
//Reset during hour 1AM
GetBoot = rtc.now();
oldReset = 0; // 0 means Arduino recently Reset during 1 AM. 1 means after reset the hour is now 2 AM and Reset has now been armed for next 1 AM.
//***************SD/Flash config and start*******************
// Start file system on the flash
flash.begin();
// Initialize flash library and check its chip ID.
if (!flash.begin()) {
Serial.println("Error, failed to initialize flash chip!");
while(1) yield();
}
Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX);
// First call begin to mount the filesystem. Check that it returns true
// to make sure the filesystem was mounted.
if (!fatfs.begin(&flash)) {
Serial.println("Error, failed to mount formatted filesystem!");
Serial.println("Was the flash chip formatted with the SdFat_format example?");
while(1) yield();
}
Serial.println("Mounted filesystem!");
File rootDir = fatfs.open("/");
if (!rootDir) {
Serial.println("Error, failed to open root directory!");
while(1) yield();
}
if (!rootDir.isDirectory()) {
Serial.println("Error, expected root to be a directory!");
while(1) yield();
}
Serial.println("Listing children of directory /:");
File child = rootDir.openNextFile();
while (child) {
char filename[64];
child.getName(filename, sizeof(filename));
// Print the file name and mention if it's a directory.
Serial.print("- "); Serial.print(filename);
if (child.isDirectory()) {
Serial.print(" (directory)");
}
Serial.println();
// Keep calling openNextFile to get a new file.
// When you're done enumerating files an unopened one will
// be returned (i.e. testing it for true/false like at the
// top of this while loop will fail).
child = rootDir.openNextFile();
}
//***************WiFi config and start*******************
// check for the presence of the WiFi shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
//**************Start and Test RA8875/Display**************
Serial.println("RA8875 start");
// Initialise the display using 'RA8875_480x272' or 'RA8875_800x480'
if (!tft.begin(RA8875_800x480)) {
Serial.println("RA8875 Not Found!");
} else {
Serial.println("Found RA8875");
//enable and Test the display
tft.displayOn(true);
tft.GPIOX(true); // Enable TFT - display enable tied to GPIOX
tft.PWM1config(true, RA8875_PWM_CLK_DIV1024); // PWM output for backlight
tft.PWM1out(255);
// With hardware accelleration this is instant
tft.fillScreen(RA8875_WHITE);
// Test with PWM
for (uint8_t i = 255; i != 0; i -= 5 )
{
tft.PWM1out(i);
delay(10);
}
for (uint8_t i = 0; i != 255; i += 5 )
{
tft.PWM1out(i);
delay(10);
}
tft.PWM1out(255);
//test file of Red, Yellow, Green, Cyan, Magenta, and Black
tft.fillScreen(RA8875_RED);
delay(500);
tft.fillScreen(RA8875_YELLOW);
delay(500);
tft.fillScreen(RA8875_GREEN);
delay(500);
tft.fillScreen(RA8875_CYAN);
delay(500);
tft.fillScreen(RA8875_MAGENTA);
delay(500);
tft.fillScreen(RA8875_BLACK);
samplingInterval = 120000; //Updates any Local data (every 120 Seconds 2 Minutes)
samplingInterval1 = 600000; //Updates Forcast and Sunset data (every 600 Seconds 10 Minutes)
displayChange = 1; //Causes loop to paint initial display
}
Serial.print("(");
Serial.print(tft.width());
Serial.print(", ");
Serial.print(tft.height());
Serial.println(")");
// Enable the touch screen
Serial.println("Enabled the touch screen");
pinMode(RA8875_INT, INPUT);
digitalWrite(RA8875_INT, HIGH);
tft.touchEnable(true);
//attachInterrupt(digitalPinToInterrupt(RA8875_INT), SIRtouch, CHANGE);
Serial.print("Status: "); Serial.println(tft.readStatus(), HEX);
Serial.println("Waiting for touch events ...");
mainGui();
guiOff();
Serial.println("The display should be off");
delay(5000);
guiOn();
Serial.println("The display should be on");
//****************Show Current Time********************
Serial.println("What is the current time");
DateTime tm = rtc.now();
time_t utc = tm.unixtime();
time_t local = myTZ.toLocal(utc, &tcr);
char ut[20];
makeDateString(utc, ut);
strcpy(ut, DtTme); //Copy Global DtTime from makeTimeString to ut
Serial.print(ut);
Serial.println(" UTC");
char lo[20];
makeDateString(local, lo);
strcpy(lo, DtTme); //Copy Global DtTime from makeTimeString to lo
Serial.print(lo);
Serial.print(" ");
Serial.println(tcr -> abbrev);
// TTN Test
//getTTNquery();
//Setup digital input pin for Display Presence Control
pinMode(inPin, INPUT); // sets the digital pin 15 as input
mark_time = millis();
previousMillis = (millis()-900000);
previousMillis1 = (millis()-900000);
}
void loop() {
//-------------------------------------------------------------------------------------------------- LOOP
checkWiFi();
float xScale = 1024.0F / tft.width();
float yScale = 1024.0F / tft.height();
//********************************************************************************
// To protect the display blank it when no one is present
dspon = digitalRead(inPin); // read the input pin
if (dspon != 1) {
/*Serial.print("millis : ");
Serial.print(millis());
Serial.print(" marked time : ");
Serial.println(mark_time);*/
if (millis () - mark_time > 30000) {
//For Small LCD displays
//display.clearDisplay();
//display.display();
//For Larger RA8875 TFT displays where the display takes a bit to paint
guiOff();
if (dsponbefore != 0) {
Serial.println("The Sensor does not sees motion - Display off");
dsponbefore = 0;
}
}
}
if (dspon == 1) {
mark_time = millis();
guiOn();
if (dsponbefore != 1) {
Serial.print("The Sensor sees motion - Display on ");
Serial.println(__FILE__);
dsponbefore = 1;
}
}
//********************************************************************************
// Wait around for touch events
if (! digitalRead(RA8875_INT))
{
if (tft.touched())
{
Serial.print(millis() - lastDebounceTime); Serial.print(" > or = < "); Serial.println(debounceDelay);
if ((millis() - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = millis(); //Debounce touch screen
Serial.print("Touch: ");
tft.touchRead(&tx, &ty);
Serial.print(tx); Serial.print(", "); Serial.println(ty);
Serial.print(tx / xScale); Serial.print(", "); Serial.println(ty / yScale);
tx = map(tx, TS_MINX, TS_MAXX, 0, tft.width());
ty = map(ty, TS_MINY, TS_MAXY, 0, tft.height());
Serial.print("("); Serial.print(tx); Serial.print(", ");
Serial.print(ty); Serial.println(") ");
SIRtouch();
// Draw a circle
tft.fillCircle((uint16_t)(tx / xScale), (uint16_t)(ty / yScale), 4, RA8875_WHITE);
} //close Debounce Touch read
} //close Touch check
} //close reading touch interrupt line
//********************************************************************************
// Look for local time 01:00 AM reset arduino on start and time hour 01 set skip alarm at hour 02 remove skip alarm
// 86400000 milliseconds per day
//Serial.print(" Current Millis = ");
//Serial.print(millis());
//Get Current UTC Time -> Extract UNIX Time -> Convert to Local Time -> Convert Time string to Char -> Convert Char to String -> Convert String to Int
GetTm = rtc.now();
GetTmutc = GetTm.unixtime();
GetTmlocal = myTZ.toLocal(GetTmutc, &tcr);
makeHrTimeString(GetTmlocal, GetTmlo);
strcpy(GetTmlo, DtTme); //Copy Global DtTime from makeTimeString to GetBootlo
GetTmloStr = String(GetTmlo);
GetTmloint = GetTmloStr.toInt();
if (GetTmloint == 1)
{
if (oldReset == 1)
{
Serial.print(GetTmloint);
Serial.println(" Reset Hour **************************");
resetFunc();
}
}
//Compare Pointer GetTmlo as uintptr_t to integer
if (GetTmloint >= 2 && oldReset != 1)
{
oldReset = 1;
Serial.print(GetTmloint);
Serial.println(" Hour");
}
//********************************************************************************
//Update weather every 60 Seconds
//convert the weather down load to use tick and update every minute
currentMillis = millis();
if (currentMillis - previousMillis > samplingInterval) {
previousMillis = currentMillis;
//
// Calculate the Boot and reset hours to be displayed during weather data update
GetBootutc = GetBoot.unixtime();
GetBootlocal = myTZ.toLocal(GetBootutc, &tcr);
makeDateString(GetBootutc, GetBootut);
strcpy(GetBootut, DtTme); //Copy Global DtTime from makeTimeString to GetBootut
Serial.print(GetBootut);
Serial.println(" UTC");
makeDateString(GetBootlocal, GetBootlo);
strcpy(GetBootlo, DtTme); //Copy Global DtTime from makeTimeString to GetBootlo
Serial.print(GetBootlo);
Serial.print(" ");
//Serial.println(tcr -> abbrev);
Serial.print(tcr -> abbrev);
Serial.println(" Local Start Time");
//
//This should be the trigger on the Arduino Reset when equal to 1
Serial.print(GetTmloint);
Serial.print(" Current Local Hour : ");
Serial.print(oldReset);
Serial.println(" Arm Value");
Serial.println("(0 = Not Armed, Just reset at 1 AM, 1 = Armed, Ready to reset at 1 AM)");
//
// rest of the commands
getLocalDataQuery();
getLocalWindMaxQuery();
getLocalWindAvgQuery();
}
//********************************************************************************
//Update Forcast and Sunset every 600 Seconds
//Open Weather Maps updates every 10 Minutes
currentMillis1 = millis();
if (currentMillis1 - previousMillis1 > samplingInterval1) {
previousMillis1 = currentMillis1;
// rest of the commands
getSunriseSunset();
getWeatherforcast();
}
//********************************************************************************
// check if display changed or if we need a refresh
if (displayChange == 1) {
if (GuidisplayState == "M1") {
mainGui();
displayChange = 0;
}
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void guiOff() {
tft.displayOn(false);
tft.PWM1out(0);
}
void guiOn() {
tft.displayOn(true);
tft.PWM1out(255);
}
//************************************************************************************************************************ Date/Time
// Convert time_t to a Date/Time string
char * makeDateString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
sprintf(DtTme, "%02d/%02d/%02d %02d:%02d:%02d", (tm.Year + 1970 - 2000), tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second); // This prints date and time
ds = DtTme;
//Serial.println(ds);
return DtTme;
}
//************************************************************************************************************************ Date
// Convert time_t to just a Date string
char * makeJustDateString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
sprintf(DtTme, "%02d/%02d/%02d", tm.Month, tm.Day, (tm.Year + 1970 - 2000)); // This prints date MM/DD/YY
ds = DtTme;
//Serial.println(ds);
return DtTme;
}
//************************************************************************************************************************ Date
// Convert time_t to just a Date string without slash in Year Month Day
char * makeAltDateString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
sprintf(DtTme, "%04d%02d%02d", (tm.Year + 1970), tm.Month, tm.Day); // This prints date YYYYMMDD
ds = DtTme;
//Serial.println(ds);
return DtTme;
}
//************************************************************************************************************************ Date
// Convert time_t to just a Date string without slash in Year Month Day
char * makeDayString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
sprintf(DtTme, "%02d", tm.Day); // This prints date DD
ds = DtTme;
//Serial.println(ds);
return DtTme;
}
/*
//************************************************************************************************************************ Date
// Convert time_t to just a Date string without slash in Year Month Day
char * makeWeekDayString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
//sprintf(DtTme, "%04d%02d%02d", (tm.Year + 1970), tm.Month,
DtTme = tm.WeekDay;
//); // This prints date YYYYMMDD
//ds = DtTme;
//Serial.println(ds);
return DtTme;
}*/
//************************************************************************************************************************ Time
// Convert time_t to a Time string
char * makeTimeString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
sprintf(DtTme, "%02d:%02d:%02d", tm.Hour, tm.Minute, tm.Second); // This prints time
ds = DtTme;
//Serial.println(ds);
return DtTme;
}
// Convert time_t to a time string Hours and Minutes
char * makeHrMinTimeString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
sprintf(DtTme, "%02d:%02d", tm.Hour, tm.Minute); // This prints time
ds = DtTme;
//Serial.println(ds);
return DtTme;
}
// Convert time_t to a time string Hours and Minutes
char * makeHrTimeString(time_t t, char *ds)
{
tmElements_t tm;
breakTime(t, tm);
sprintf(DtTme, "%01d", tm.Hour); // This prints time
ds = DtTme;
//Serial.println(ds);
return DtTme;
}
//************************************************************************************************************************ M1 Main GUI
void mainGui() {
//reset-clear display
tft.graphicsMode(); // go back to graphics mode
tft.fillScreen(RA8875_BLACK);
tft.graphicsMode();
bmpDraw("SUNFLSST.BMP", 0, 0);
//tft.fillScreen(RA8875_MAGENTA);
//tft.fillScreen(RA8875_BLUE);
tft.fillScreen(DRKTURQUOISE);
// display is 800 x 480; 164mm x 100mm x 5mm; 6.5" x 3.9" 0.2"
// 123 Pixels Per Inch
// 4 buttons 46 pixels tall about 3/8" and 101 pixels wide about 3/4"
// 5 buttons 46 pixels tall about 3/8" and 78 pixels wide about 5/8"
// 15 pixel space between buttons
// bottom of button about 8 pixels up
// Example fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
tft.fillRoundRect(14, 427, 101, 46, 23, 0xFE20);
tft.fillRoundRect(130, 427, 101, 46, 23, 0xFE20);
tft.fillRoundRect(246, 427, 101, 46, 23, 0xFE20);
tft.fillRoundRect(362, 427, 101, 46, 23, 0xFE20);
tft.fillRoundRect(483, 381, 308, 92, 46, MEDTURQUOISE);
tft.fillRect(9, 15, 150, 200, MEDTURQUOISE);
tft.fillRect(167, 15, 150, 200, MEDTURQUOISE);
tft.fillRect(325, 15, 150, 200, MEDTURQUOISE);
tft.fillRect(483, 15, 150, 200, MEDTURQUOISE);
tft.fillRect(641, 15, 150, 200, MEDTURQUOISE);
tft.fillRect(9, 230, 150, 135, MEDTURQUOISE);
tft.fillRect(167, 230, 150, 135, MEDTURQUOISE);
tft.fillRect(325, 230, 150, 135, MEDTURQUOISE);
tft.fillRect(483, 230, 150, 135, MEDTURQUOISE);
tft.fillRect(641, 230, 150, 135, MEDTURQUOISE);
tft.textMode(); // go to text mode
//tft.setFont(&FreeSansBold24pt7b);
//void setCursor(uint16_t x0, uint16_t y0);
//void setTextColor(uint16_t color);
tft.textSetCursor(35, 440);
tft.textTransparent(BROWN);
//tft.textEnlarge(3);
tft.textWrite("Weather");
tft.graphicsMode();
GuidisplayState[1] = 'M';
GuidisplayState[2] = '1';
}
//************************************************************************************************************************ Check WiFi
void checkWiFi() {
if ( WiFi.status() != WL_CONNECTED) {
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// unsuccessful, retry in 4 seconds
Serial.print("failed ... ");
delay(4000);
Serial.print("retrying ... ");
}
}
}
//************************************************************************************************************************ BMP Draw
void bmpDraw(const char *filename, int x, int y) {
// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates. It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel). Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster. 20 pixels seems a
// good balance.
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
uint16_t lcdbuffer[BUFFPIXEL]; // pixeindex1l out buffer (16-bit per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean goodBmp = false; // Set to true on valid header parse
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col;
uint8_t r, g, b;
uint32_t pos = 0, startTime = millis();
uint8_t lcdidx = 0;
boolean first = true;
if ((x >= tft.width()) || (y >= tft.height())) return;
Serial.println();
Serial.print(F("Loading image '"));
Serial.print(filename);
Serial.println('\'');
// Open requested file on SD card
if ((bmpFile = fatfs.open(filename)) == false) {
Serial.println(F("File not found"));
return;
}
// Parse BMP header
if (read16(bmpFile) == 0x4D42) { // BMP signature
Serial.println(F("File size: "));
Serial.println(read32(bmpFile));
(void)read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
Serial.print(F("Image Offset: "));
Serial.println(bmpImageoffset, DEC);
// Read DIB header
Serial.print(F("Header size: "));
Serial.println(read32(bmpFile));
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
Serial.print(F("width: "));
Serial.print(bmpWidth, DEC);
Serial.print(F(" height: "));
Serial.println(bmpHeight, DEC);
if (read16(bmpFile) == 1) { // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
Serial.print(F("Bit Depth: "));
Serial.println(bmpDepth);
if ((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
goodBmp = true; // Supported BMP format -- proceed!
Serial.print(F("Image size: "));
Serial.print(bmpWidth);
Serial.print('x');
Serial.println(bmpHeight);
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if (bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
}
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if ((x + w - 1) >= tft.width()) w = tft.width() - x;
if ((y + h - 1) >= tft.height()) h = tft.height() - y;
// Set TFT address window to clipped image bounds
for (row = 0; row < h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if (bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col = 0; col < w; col++) { // For each column...
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
// Push LCD buffer to the display first
if (lcdidx > 0) {
tft.drawPixel(col + x, row + y, lcdbuffer[lcdidx]);
lcdidx = 0;
first = false;
}
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}
// Convert pixel from BMP to TFT format
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
lcdbuffer[lcdidx] = color565(r, g, b);
tft.drawPixel(col + x, row + y, lcdbuffer[lcdidx]);
} // end pixel
} // end scanline
// Write any remaining data to LCD
if (lcdidx > 0) {
tft.drawPixel(col + x, row + y, lcdbuffer[lcdidx]);
}
Serial.print(F("Loaded in "));
Serial.print(millis() - startTime);
Serial.println(" ms");
} // end goodBmp
}
}
bmpFile.close();
if (!goodBmp) Serial.println(F("BMP format not recognized."));
}
//************************************************************************************************************************ Read 16/32 bit files from SD
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.
uint16_t read16(File f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}
uint32_t read32(File f) {
uint32_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read();
((uint8_t *)&result)[2] = f.read();
((uint8_t *)&result)[3] = f.read(); // MSB
return result;
}
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) {
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
byte decToBcd(byte val) {
// Convert normal decimal numbers to binary coded decimal
return ( (val / 10 * 16) + (val % 10) );
}
//************************************************************************************************************************ Touch Point Routines
// ***************************************************************************
// Touch point routines
// ***************************************************************************
void SIRtouch() {
//Serial.print("Touch: ");
if ((tx >= 10) && (tx <= 131) && (ty >= 917) && (ty <= 992)) {
GuidisplayState[1] = 'M';
GuidisplayState[2] = '1';
}
else
{
if ((tx >= 159) && (tx <= 261) && (ty >= 917) && (ty <= 992)) {
GuidisplayState[1] = 'M';
GuidisplayState[2] = '2';
}
else
{
if ((tx >= 315) && (tx <= 434) && (ty >= 917) && (ty <= 992)) {
GuidisplayState[1] = 'M';
GuidisplayState[2] = '3';
}
else
{
if ((tx >= 457) && (tx <= 588) && (ty >= 917) && (ty <= 992)) {
GuidisplayState[1] = 'M';
GuidisplayState[2] = '4';
}
}
}
}
}
//************************************************************************************************************************ Time Convert - This may not be needed
time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss)
{
tmElements_t tmSet;
tmSet.Year = YYYY - 1970;
tmSet.Month = MM;
tmSet.Day = DD;
tmSet.Hour = hh;
tmSet.Minute = mm;
tmSet.Second = ss;
return makeTime(tmSet); //convert to time_t
}
time_t convertToTime(String calTimestamp) {
struct tm tm;
//Serial.println("Parsing " + calTimestamp);
//Format 2021-12-30 03:00:00
String year = calTimestamp.substring(0, 4);
String month = calTimestamp.substring(5, 7);
if (month.startsWith("0")) {
month = month.substring(1);
}
String day = calTimestamp.substring(8, 10);
if (day.startsWith("0")) {
month = day.substring(1);
}
tm.tm_year = year.toInt() - 1900;
tm.tm_mon = month.toInt() - 1;
tm.tm_mday = day.toInt();
tm.tm_hour = calTimestamp.substring(11, 13).toInt();
tm.tm_min = calTimestamp.substring(14, 16).toInt();
tm.tm_sec = calTimestamp.substring(17, 19).toInt();
return mktime(&tm);
}
time_t stringUtcToLocal(String FCTime) {
struct tm tm;
DateTime FCtm = convertToTime(FCTime);
time_t FCutc = FCtm.unixtime();
time_t FCloc = myTZ.toLocal(FCutc, &tcr);
return FCloc;
}
/*
#############################################################################
# Get data from The Local InfluxDB
#
*/
void getLocalWindAvgQuery() {
Serial.println("\nStarting connection to Docker Container PHP-Apache: InfluxDB WindAvg...");
// if you get a connection, report back via serial:
if (client.connect(server1, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /WindAvg.php");//http://10.197.1.100/WindAvg.php
} else {
Serial.println("************************unable to connect************************");
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// unsuccessful, retry in 4 seconds
Serial.print("failed ... ");
delay(4000);
Serial.print("retrying ... ");
}
}
delay(1000);
String line = "";
while (client.connected()) {
line = client.readStringUntil('\n');
//Serial.println(line);
Serial.print("Line : "); Serial.println(line);
Serial.println("parsingValues");
//create a json buffer where to store the json data
StaticJsonBuffer<1000> jsonBuffer; //Arduinojson5
JsonObject& root = jsonBuffer.parseObject(line); //Arduinojson5
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
//get the data from the json tree
char windavg[10];
float wndavg = root["results"][0]["series"][0]["values"][0][1];
dtostrf(wndavg, 6, 0, windavg);
Serial.print(" @-Min Wind Average : ");
Serial.println(windavg);
// Display the Values
tft.textMode(); // go to text mode
tft.textTransparent(RA8875_WHITE); // set text color
tft.textEnlarge(0);
tft.textSetCursor(486, 90);
tft.textWrite("Wind 2-Min Average");
tft.textSetCursor(595, 108);
tft.textWrite("MPH");
tft.textEnlarge(2);
tft.textSetCursor(450, 108);
tft.textWrite(windavg);
}
}
void getLocalWindMaxQuery() {
Serial.println("\nStarting connection to Docker Container PHP-Apache: InfluxDB WindMax...");
// if you get a connection, report back via serial:
if (client.connect(server1, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /WindMax.php");//http://10.197.1.100/WindMax.php
} else {
Serial.println("************************unable to connect************************");
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// unsuccessful, retry in 4 seconds
Serial.print("failed ... ");
delay(4000);
Serial.print("retrying ... ");
}
}
delay(1000);
String line = "";
while (client.connected()) {
line = client.readStringUntil('\n');
//Serial.println(line);
Serial.print("Line : "); Serial.println(line);
Serial.println("parsingValues");
//create a json buffer where to store the json data
StaticJsonBuffer<1000> jsonBuffer; //Arduinojson5
JsonObject& root = jsonBuffer.parseObject(line); //Arduinojson5
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
//get the data from the json tree
char windmax[10];
float wndmax = root["results"][0]["series"][0]["values"][0][1];
dtostrf(wndmax, 6, 0, windmax);
Serial.print(" 1 Hour Max Gust : ");
Serial.println(windmax);
// Display the Values
tft.textMode(); // go to text mode
tft.textTransparent(RA8875_WHITE); // set text color
tft.textEnlarge(0);
tft.textSetCursor(486, 150);
tft.textWrite("Wind 1-Hr Max Gust");
tft.textSetCursor(595, 168);
tft.textWrite("MPH");
tft.textEnlarge(2);
tft.textSetCursor(450, 168);
tft.textWrite(windmax);
}
}
void getLocalDataQuery() {
Serial.println("\nStarting connection to Docker Container PHP-Apache: InfluxDB index1...");
// if you get a connection, report back via serial:
if (client.connect(server1, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /index1.php");//http://10.197.1.100/index1.php
} else {
Serial.println("************************unable to connect************************");
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// unsuccessful, retry in 4 seconds
Serial.print("failed ... ");
delay(4000);
Serial.print("retrying ... ");
}
}
delay(1000);
String line = "";
while (client.connected()) {
line = client.readStringUntil('\n');
//Serial.println(line);
Serial.print("Line : "); Serial.println(line);
Serial.println("parsingValues");
//create a json buffer where to store the json data
StaticJsonBuffer<1000> jsonBuffer; //Arduinojson5
JsonObject& root = jsonBuffer.parseObject(line); //Arduinojson5
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
Serial.print("Line : "); Serial.println(line);
//get the data from the json tree
char temp[10];
//String stemp;
char heatindex[10];
char dewpoint[10];
char humidity[10];
char pressure[10];
char soiltemp[10];
char rainfall[10];
char windspeed[10];
char winddirection[5];
char windchill[10];
char batteryvolt[10];
int dx;
int dy;
int dxOuter, dyOuter, dxinner, dyinner;
//Setup Wind indicator parameters
const int windX = 716;
const int windY = 92;
const int diam = 55;
const char* cUtcTime;
//String cUtcTime;
//Convert float(s) & int(s) to displayable Strings
//unsigned long epoch = (((year/4*(365*4+1)+days[year%4][month]+dayOfMonth)*24+hour)*60+minute)*60+second
int StatementID = root["results"]["statement_id"];
Serial.print("Statement ID : ");
Serial.println(StatementID);
const char* StationNme = root["results"][0]["series"][0]["name"];
Serial.print("name : ");
Serial.println(StationNme);
//Time
cUtcTime = root["timeStamp"]; //Extracts the timeStamp to a const char*
String sUtcTime(cUtcTime); // converts const char* to String //next step convert from String to time_t
//time_t utctime = sUtcTime
//time_t utctime = root["timeStamp"];
//Temperature
float tmp = root["results"][0]["series"][0]["values"][0][8];
dtostrf(tmp, 5, 0, temp); // Converts float to char with no decimal
//Humidity
float h1 = root["results"][0]["series"][0]["values"][0][2];
int h2 = h1 * 10;
float hum = h2 / 10;
dtostrf(hum, 5, 0, humidity);
//Pressure
float p1 = root["results"][0]["series"][0]["values"][0][4];
int p2 = p1 * 10;
float prssure = p2 / 10;
dtostrf(prssure, 7, 1, pressure);
//float soilmoisture = root["results"][0]["series"][0]["values"][0][3];
//float csoiltemp = root["results"][0]["series"][0]["values"][0][6];
//float soiltmp = (csoiltemp * 1.8) + 32;
//dtostrf(soiltmp, 5, 0, soiltemp);
//Rainfall
float rfall = root["results"][0]["series"][0]["values"][0][5];
dtostrf(rfall, 7, 4, rainfall);
//Wind Speed
float wndspeed = root["results"][0]["series"][0]["values"][0][12];
dtostrf(wndspeed, 6, 0, windspeed);
//Wind Direction
float wnddirect = root["results"][0]["series"][0]["values"][0][11];
dtostrf(wnddirect, 4, 0, winddirection);
// Wind Chill
//float cwndchll = root["windchill"];
//T(wc) = 0.0817(3.71V**0.5 + 5.81 -0.25V)(T - 91.4) + 91.4 T(wc); (wind chill old Formula),
//T(wc) = 35.74 + 0.6215*T - 35.75(V^0.16) + 0.4275*T(V^0.16); (wind chill new Formula),
//V is in the wind speed in statute miles per hour
//T is the temperature in degrees Fahrenheit.
float wndchill;
if (tmp > 50 || wndspeed ==0){
wndchill = tmp;
} else {
float T = tmp;
float V = wndspeed;
wndchill = 35.74 + (0.6215*T) - (35.75*pow(V,0.16)) + (0.4275*T*pow(V,0.16));
}
dtostrf(wndchill, 5, 0, windchill);
Serial.print("Windchill : ");
Serial.print(windchill);
// Heatindex (this will need to be calculated)
float chtindx = root["heatindex"];
//Heat Index
double htindx;
double Dtempf = tmp;
double Dhumid = hum;
if (tmp < 80 || hum < 40){
htindx = tmp;
} else {
htindx = heatIndex(Dtempf,Dhumid);
}
dtostrf(htindx, 5, 0, heatindex);
Serial.print("Heat Index : ");
Serial.print(heatindex);
//Dew Point Calculations
// DP = T - ((100 - RH)/5) T= Temperature & RH = Relative Humidity
double C = ((tmp - 32) * (5/9) );
double H = hum;
double DwPnt = (C - ((100 - H) / 5)); // dewpoint calculation using Celsius value
float DwPoint = (DwPnt * 9 / 5) + 32; // converts dewPoint calculation to fahrenheit
dtostrf(DwPoint, 5, 0, dewpoint);
Serial.print("Dew Point : ");
Serial.println(dewpoint);
//Battery Voltage
float batv = root["results"][0]["series"][0]["values"][0][10];
dtostrf(batv, 7, 3, batteryvolt);
//
DateTime tm = rtc.now();
time_t utc = tm.unixtime();
time_t local = myTZ.toLocal(utc, &tcr);
char lo[20];
char lod[20];
makeHrMinTimeString(local, lo);
strcpy(lo, DtTme); //Copy Global DtTime from makeTimeString to lo
makeJustDateString(local, lo);
strcpy(lod, DtTme); //Copy Global DtTime from makeTimeString to lod
// Print values.
Serial.print("Current Time : ");
// Serial.print(utctime);
Serial.print(lo);
Serial.print(" ");
Serial.println(tcr -> abbrev);
Serial.print(" Temperature : ");
Serial.print(temp);
Serial.print(" Humidity : ");
Serial.println(humidity);
Serial.print("Pressure : ");
Serial.print(pressure);
Serial.print(" Rainfall : ");
Serial.print(rainfall);
Serial.print(" Battery : ");
Serial.println(batteryvolt);
Serial.print(" WindSpeed : ");
Serial.print(windspeed);
Serial.print(" Wind Direction : ");
Serial.println(winddirection);
/**/
tft.graphicsMode();
tft.fillRect(167, 15, 150, 200, MEDTURQUOISE); //Temperature Box
tft.fillRect(325, 15, 150, 200, MEDTURQUOISE); //Humidity Box
tft.fillRect(483, 15, 150, 200, MEDTURQUOISE); //Pressure Box
tft.fillRect(641, 15, 150, 200, MEDTURQUOISE); //Wind Box
tft.fillRoundRect(483, 381, 308, 92, 46, MEDTURQUOISE); //Date Time station Voltage
// Display the Values
tft.textMode(); // go to text mode
tft.textTransparent(RA8875_WHITE); // set text color
tft.textEnlarge(0);
tft.textSetCursor(170, 20);
tft.textWrite("Temperature");
tft.textSetCursor(295, 40);
tft.textWrite("F");
tft.textSetCursor(295, 110);
tft.textWrite("F");
tft.textSetCursor(295, 170);
tft.textWrite("F");
tft.textSetCursor(170, 90);
tft.textWrite("Wind Chill");
tft.textSetCursor(170, 150);
tft.textWrite("Heat Index");
tft.textSetCursor(328, 20);
tft.textWrite("Humidity");
tft.textSetCursor(433, 40);
tft.textWrite("% RH");
tft.textSetCursor(453, 110);
tft.textWrite("F");
tft.textSetCursor(328, 90);
tft.textWrite("Dew Point");
tft.textSetCursor(486, 20);
tft.textWrite("Pressure");
tft.textSetCursor(590, 40);
tft.textWrite("\" Hg");
tft.textSetCursor(644, 20);
tft.textWrite("Wind");
tft.textSetCursor(758, 170);
tft.textWrite("MPH");
tft.textSetCursor(580, 402);
tft.textWrite(tcr -> abbrev); //Current Time Zone
tft.textSetCursor(650, 440);
tft.textWrite("Batt : ");
tft.textWrite(batteryvolt);
tft.textWrite(" V");
/**/
tft.textEnlarge(2);
tft.textSetCursor(160, 35);
tft.textWrite(temp);
tft.textSetCursor(160, 100);
tft.textWrite(windchill);
tft.textSetCursor(160, 160);
tft.textWrite(heatindex);
tft.textSetCursor(318,100);
tft.textWrite(dewpoint);
tft.textEnlarge(2);
tft.textSetCursor(311, 35);
tft.textWrite(humidity);
tft.textSetCursor(418, 35);
tft.textWrite(pressure);
tft.textSetCursor(540, 155);
tft.textWrite(windspeed);
/**/
tft.textEnlarge(1);
tft.textSetCursor(490, 399);
tft.textWrite(lo); //Local Time
tft.textSetCursor(490, 428); //for date
tft.textWrite(lod); // Local Date
//Reset to TextEnlarge 0 and to Graphics mode
tft.textEnlarge(0);
tft.graphicsMode();
//*--------------------------------------------------------------
// Start WIND COMPASS ROSE and place Wind Direction Indicator
//
// Draw Circle center at windX, windY and sized with diam
tft.drawCircle(windX, windY, diam, RA8875_WHITE);
// 90 Degree Hash Marks
tft.drawLine((windX - diam - 5), windY, (windX - diam + 5), windY, RA8875_CYAN);
tft.drawLine((windX + diam - 5), windY, (windX + diam + 5), windY, RA8875_CYAN);
tft.drawLine(windX, (windY - diam - 5), windX, (windY - diam + 5), RA8875_CYAN);
tft.drawLine(windX, (windY + diam - 5), windX, (windY + diam + 5), RA8875_CYAN);
// add the Four Ordinal points - 45 Degree Hash Marks
for (float i = 0; i < 360; i = i + 45 )
{
dxOuter = (diam * cos((i - 90) * 3.14 / 180));
dyOuter = (diam * sin((i - 90) * 3.14 / 180));
dxinner = dxOuter * 0.92;
dyinner = dyOuter * 0.92;
tft.drawLine((dxinner + windX), (dyinner + windY), (dxOuter + windX), (dyOuter + windY), RA8875_CYAN);
}
// Add the Eight half-winds - 22.5 Degree Hash Marks
for (float i = 0; i < 360; i = i + 22.5 )
{
dxOuter = (diam * cos((i - 90) * 3.14 / 180));
dyOuter = (diam * sin((i - 90) * 3.14 / 180));
dxinner = dxOuter * 0.95;
dyinner = dyOuter * 0.95;
tft.drawLine((dxOuter + windX), (dyOuter + windY), (dxinner + windX), (dyinner + windY), RA8875_CYAN);
}
// Add the Sixteen quarter-winds - 11.25 Degree Hash Marks
// My current Windirection device does not support quarter winds
for (float i = 0; i < 360; i = i + 11.25 )
{
dxOuter = diam * cos((i - 90) * 3.14 / 180);
dyOuter = diam * sin((i - 90) * 3.14 / 180);
dxinner = dxOuter * 0.98;
dyinner = dyOuter * 0.98;
tft.drawLine((dxOuter + windX), (dyOuter + windY), (dxinner + windX), (dyinner + windY), RA8875_CYAN);
}
//Windirection Indicator
/**/
dx = (diam * .9 * cos((wnddirect - 90) * 3.14 / 180)) + windX; // calculate X position
dy = (diam * .9 * sin((wnddirect - 90) * 3.14 / 180)) + windY; // calculate Y position
tft.drawLine(dx, dy, windX, windY, RA8875_RED);
/**/
//Add N,S,E,W near cardinal hash marks
tft.textMode();
tft.textTransparent(RED);
tft.textEnlarge(0);
tft.textSetCursor((windX - 3), (windY - (diam + 18)));
tft.textWrite("N");
tft.textTransparent(YELLOW);
tft.textSetCursor((windX - 3), (windY + (diam + 4)));
tft.textWrite("S");
tft.textSetCursor((windX + (diam + 7)), (windY - 8));
tft.textWrite("E");
tft.textSetCursor((windX - (diam + 13)), (windY - 8)); //X was 12 almost no gap from end of dash needs to go left
tft.textWrite("W");
//
tft.graphicsMode();
// Finished with WIND COMPASS ROSE
}
}
void ShowMaxMin(int xcnt, float tmax, float tmin) {
Serial.print("Day ");
Serial.print(xcnt);
Serial.print(" Max Temp ");
Serial.print(tmax);
Serial.print(" Min Temp ");
Serial.println(tmin);
}
double heatIndex(double tempF, double Humidity){
//Heat Index from: https://www.weather.gov/ama/heatindex#:~:text=The%20heat%20index%2C%20also%20known,sweat%20to%20cool%20itself%20off
//Heat Index = -42.379 + 2.04901523T + 10.14333127R - 0.22475541TR - 6.83783 x 10-3T2 - 5.481717 x 10-2R2 + 1.22874 x 10-3T2R + 8.5282 x 10-4TR2 - 1.99 x 10-6T2R2
// Where T = Temperature in F
// R = Relative humidity
//
double T = tempF;
double R = Humidity;
double HI = -42.379 + 2.04901523*T + 10.14333127*R - 0.22475541*T*R - 0.00683783*T*T - 0.05481717*R*R + 0.00122874*T*T*R + 0.00085282*T*R*R - 0.00000199*T*T*R*R;
return HI;
}
void getWeatherforcast() {
Serial.println("\nStarting connection to server: api.openweathermap.org Weather Forecast...");
// if you get a connection, report back via serial:
//https ://api.openweathermap.org/data/2.5/onecall?lat=37.5644615&lon=-97.3522675&units=imperial&exclude=minutely,hourly,alerts&appid=4e8bda75d9c60964
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.print("GET /data/2.5/onecall?");
//client.print("id="+location);
//lat=37.5644615&lon=-97.3522675
client.print("lat=37.5644615");
client.print("&lon=-97.3522675");
client.print("&units=imperial"); // imperial= Fahrenheit, metric= Celsius,default is Kelvin
client.print("&exclude=minutely,hourly,alerts");
client.println("&appid="+apiKey);
client.println("Host: api.openweathermap.org");
client.println("Connection: close");
client.println();
} else {
Serial.println("************************unable to connect************************");
WiFi.disconnect();
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// unsuccessful, retry in 4 seconds
Serial.print("failed ... ");
delay(4000);
Serial.print("retrying ... ");
}
}
delay(1000);
String line = "";
while (client.connected()) {
line = client.readStringUntil('\n');
Serial.println(line);
Serial.println("parsingValues");
//create a json buffer where to store the json data
StaticJsonBuffer<24000> jsonBuffer; //Arduinojson5
JsonObject& root = jsonBuffer.parseObject(line); //Arduinojson5
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
//get the data from the json tree
//declare reused time Variables
char FClo[20];
char FClod[20];
String FClodPrev; //Do I need this
int dow;
String DayoWeek;
//Todays Forcast
String ftimestr0 = root["daily"][0]["dt"];
time_t fsttm = ftimestr0.toInt();
time_t FCloc = myTZ.toLocal(fsttm, &tcr);
dow=(((FCloc / 86400) + 4) % 7);
DayoWeek = daysOfTheWeek[dow];
char FCDOW00[10];
DayoWeek.toCharArray(FCDOW00, 10);
Serial.print("Todays Forecast ");
Serial.print(dow);
Serial.print(" ");
Serial.println(DayoWeek);
makeHrMinTimeString(FCloc, FClo);
strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
makeJustDateString(FCloc, FClod);
strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod
FClodPrev = FClod; //This is the first date so it is always unique // Do I need this
String FCTimeD00 = FClod;
String FCTime00 = FClo;
double FCTmp00 = root["daily"][0]["temp"]["max"];
char FCTemp00[5];
dtostrf(FCTmp00, 4, 0, FCTemp00);
double FCTmpL00 = root["daily"][0]["temp"]["min"];
char FCTempL00[5];
dtostrf(FCTmpL00, 4, 0, FCTempL00);
double FCHum00 = root["daily"][0]["humidity"];
char FCHumid00[5];
dtostrf(FCHum00, 4, 0, FCHumid00);
String FCSky00 = root["daily"][0]["weather"][0]["main"];
double FCWSpd00 = root["daily"][0]["wind_speed"];
double FCWDir00 = root["daily"][0]["wind_deg"];
double FCWGst00 = root["daily"][0]["wind_gust"];
//dtostrf(DwPoint, 5, 0, dewpoint);
//Test if Rain or Snow is present then set else set to 0
double FCPo00 = root["daily"][0]["pop"]; // Probability
int FCPop00 = FCPo00 * 100;
char FCProb00[5];
dtostrf(FCPop00, 4, 0, FCProb00);
double FCRn00 = root["daily"][0]["rain"];// Rain Amount
double FCSn00 = root["daily"][0]["snow"];// Snow Amount
char FCRain00[5];
if (!FCRn00 && !FCSn00) {
FCRn00=0;
} else {
if (!FCRn00) {
FCRn00 = FCSn00;
}
}
dtostrf(FCRn00, 4, 0, FCRain00);
//Day 1 Forcast
String ftimestr1 = root["daily"][1]["dt"];
fsttm = ftimestr1.toInt();
FCloc = myTZ.toLocal(fsttm, &tcr);
//Day of Week
dow=(((FCloc / 86400) + 4) % 7);
DayoWeek = daysOfTheWeek[dow];
char FCDOW01[10];
DayoWeek.toCharArray(FCDOW01, 10);
// Day of Week End
makeHrMinTimeString(FCloc, FClo);
strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
makeJustDateString(FCloc, FClod);
strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod
FClodPrev = FClod; //This is the first date so it is always unique // Do I need this
String FCTimeD01 = FClod; // We will always need the first date
String FCTime01 = FClo;
double FCTmp01 = root["daily"][1]["temp"]["max"];
char FCTemp01[5];
dtostrf(FCTmp01, 4, 0, FCTemp01);
double FCTmpL01 = root["daily"][1]["temp"]["min"];
char FCTempL01[5];
dtostrf(FCTmpL01, 4, 0, FCTempL01);
double FCHum01 = root["daily"][1]["humidity"];
char FCHumid01[5];
dtostrf(FCHum01, 4, 0, FCHumid01);
String FCSky01 = root["daily"][1]["weather"][0]["main"];
String FCWSpd01 = root["daily"][1]["wind_speed"];
String FCWDir01 = root["daily"][1]["wind_deg"];
String FCWGst01 = root["daily"][1]["wind_gust"];
//Test if Rain or Snow is present then set else set to 0
double FCPo01 = root["daily"][1]["pop"]; // Probability
int FCPop01 = FCPo01 * 100;
char FCProb01[5];
dtostrf(FCPop01, 4, 0, FCProb01);
double FCRn01 = root["daily"][1]["rain"];// Rain Amount
double FCSn01 = root["daily"][1]["snow"];// Snow Amount
char FCRain01[5];
if (!FCRn01 && !FCSn01) {
FCRn01=0;
} else {
if (!FCRn01) {
FCRn01 = FCSn01;
}
}
dtostrf(FCRn01, 4, 0, FCRain01);
//Day 2 Forcast
String ftimestr2 = root["daily"][2]["dt"];
fsttm = ftimestr2.toInt();
FCloc = myTZ.toLocal(fsttm, &tcr);
//Day of Week
dow=(((FCloc / 86400) + 4) % 7);
DayoWeek = daysOfTheWeek[dow];
char FCDOW02[10];
DayoWeek.toCharArray(FCDOW02, 10);
// Day of Week End
makeHrMinTimeString(FCloc, FClo);
strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
makeJustDateString(FCloc, FClod);
strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod
FClodPrev = FClod; //This is the first date so it is always unique // Do I need this
String FCTimeD02 = FClod; // We will always need the first date
String FCTime02 = FClo;
double FCTmp02 = root["daily"][2]["temp"]["max"];
char FCTemp02[5];
dtostrf(FCTmp02, 4, 0, FCTemp02);
double FCTmpL02 = root["daily"][2]["temp"]["min"];
char FCTempL02[5];
dtostrf(FCTmpL02, 4, 0, FCTempL02);
double FCHum02 = root["daily"][2]["humidity"];
char FCHumid02[5];
dtostrf(FCHum02, 4, 0, FCHumid02);
String FCSky02 = root["daily"][2]["weather"][0]["main"];
String FCWSpd02 = root["daily"][2]["wind_speed"];
String FCWDir02 = root["daily"][2]["wind_deg"];
String FCWGst02 = root["daily"][2]["wind_gust"];
//Test if Rain or Snow is present then set else set to 0
double FCPo02 = root["daily"][2]["pop"]; // Probability
int FCPop02 = FCPo02 * 100;
char FCProb02[5];
dtostrf(FCPop02, 4, 0, FCProb02);
double FCRn02 = root["daily"][2]["rain"];// Rain Amount
double FCSn02 = root["daily"][2]["snow"];// Snow Amount
char FCRain02[5];
if (!FCRn02 && !FCSn02) {
FCRn02=0;
} else {
if (!FCRn02) {
FCRn02 = FCSn02;
}
}
dtostrf(FCRn02, 4, 0, FCRain02);
//Day 3 Forcast
String ftimestr3 = root["daily"][3]["dt"];
fsttm = ftimestr3.toInt();
FCloc = myTZ.toLocal(fsttm, &tcr);
//Day of Week
dow=(((FCloc / 86400) + 4) % 7);
DayoWeek = daysOfTheWeek[dow];
char FCDOW03[10];
DayoWeek.toCharArray(FCDOW03, 10);
// Day of Week End
makeHrMinTimeString(FCloc, FClo);
strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
makeJustDateString(FCloc, FClod);
strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod
FClodPrev = FClod; //This is the first date so it is always unique // Do I need this
String FCTimeD03 = FClod; // We will always need the first date
String FCTime03 = FClo;
double FCTmp03 = root["daily"][3]["temp"]["max"];
char FCTemp03[5];
dtostrf(FCTmp03, 4, 0, FCTemp03);
double FCTmpL03 = root["daily"][3]["temp"]["min"];
char FCTempL03[5];
dtostrf(FCTmpL03, 4, 0, FCTempL03);
// String FCHumid03 = root["daily"][3]["humidity"];
double FCHum03 = root["daily"][3]["humidity"];
char FCHumid03[5];
dtostrf(FCHum03, 4, 0, FCHumid03);
String FCSky03 = root["daily"][3]["weather"][0]["main"];
String FCWSpd03 = root["daily"][3]["wind_speed"];
String FCWDir03 = root["daily"][3]["wind_deg"];
String FCWGst03 = root["daily"][3]["wind_gust"];
//Test if Rain or Snow is present then set else set to 0
double FCPo03 = root["daily"][3]["pop"]; // Probability
int FCPop03 = FCPo03 * 100;
char FCProb03[5];
dtostrf(FCPop03, 4, 0, FCProb03);
double FCRn03 = root["daily"][3]["rain"];// Rain Amount
double FCSn03 = root["daily"][3]["snow"];// Snow Amount
char FCRain03[5];
if (!FCRn03 && !FCSn03) {
FCRn03=0;
} else {
if (!FCRn03) {
FCRn03 = FCSn03;
}
}
dtostrf(FCRn03, 4, 0, FCRain03);
//Day 4 Forcast
String ftimestr4 = root["daily"][4]["dt"];
fsttm = ftimestr4.toInt();
FCloc = myTZ.toLocal(fsttm, &tcr);
//Day of Week
dow=(((FCloc / 86400) + 4) % 7);
DayoWeek = daysOfTheWeek[dow];
char FCDOW04[10];
DayoWeek.toCharArray(FCDOW04, 10);
// Day of Week End
makeHrMinTimeString(FCloc, FClo);
strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
makeJustDateString(FCloc, FClod);
strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod
FClodPrev = FClod; //This is the first date so it is always unique // Do I need this
String FCTimeD04 = FClod; // We will always need the first date
String FCTime04 = FClo;
double FCTmp04 = root["daily"][4]["temp"]["max"];
char FCTemp04[5];
dtostrf(FCTmp04, 4, 0, FCTemp04);
double FCTmpL04 = root["daily"][4]["temp"]["min"];
char FCTempL04[5];
dtostrf(FCTmpL04, 4, 0, FCTempL04);
// String FCHumid04 = root["daily"][4]["humidity"];
double FCHum04 = root["daily"][4]["humidity"];
char FCHumid04[5];
dtostrf(FCHum04, 4, 0, FCHumid04);
String FCSky04 = root["daily"][4]["weather"][0]["main"];
String FCWSpd04 = root["daily"][4]["wind_speed"];
String FCWDir04 = root["daily"][4]["wind_deg"];
String FCWGst04 = root["daily"][4]["wind_gust"];
//Test if Rain or Snow is present then set else set to 0
double FCPo04 = root["daily"][4]["pop"]; // Probability
int FCPop04 = FCPo04 * 100;
char FCProb04[5];
dtostrf(FCPop04, 4, 0, FCProb04);
double FCRn04 = root["daily"][4]["rain"];// Rain Amount
double FCSn04 = root["daily"][4]["snow"];// Snow Amount
char FCRain04[5];
if (!FCRn04 && !FCSn04) {
FCRn04=0;
} else {
if (!FCRn04) {
FCRn04 = FCSn04;
}
}
dtostrf(FCRn04, 4, 0, FCRain04);
// Print values.
Serial.print("Date Time ");
Serial.print("Max-Temp/F-Min");
Serial.print(" Humidity ");
Serial.print(" Wind Speed/MPH ");
Serial.print(" Direction ");
Serial.print(" Gust/MPH ");
Serial.print(" Rain-Snow ");
Serial.print(" Sky ");
Serial.println("");
//Current
Serial.print(FCTimeD00);
Serial.print(" ");
Serial.print(FCTemp00);
Serial.print(" ");
Serial.print(FCTempL00);
Serial.print(" ");
Serial.print(FCHumid00);
Serial.print(" ");
Serial.print(FCWSpd00);
Serial.print(" ");
Serial.print(FCWDir00);
Serial.print(" ");
Serial.print(FCWGst00);
Serial.print(" ");
Serial.print(FCRain00);
Serial.print(" - ");
Serial.print(FCProb00);
Serial.print(" ");
Serial.print(FCSky00);
Serial.println("");
//Day 1
Serial.print(FCTimeD01);
Serial.print(" ");
Serial.print(FCTemp01);
Serial.print(" ");
Serial.print(FCTempL01);
Serial.print(" ");
Serial.print(FCHumid01);
Serial.print(" ");
Serial.print(FCWSpd01);
Serial.print(" ");
Serial.print(FCWDir01);
Serial.print(" ");
Serial.print(FCWGst01);
Serial.print(" ");
Serial.print(FCRain01);
Serial.print(" - ");
Serial.print(FCProb01);
Serial.print(" ");
Serial.print(FCSky01);
Serial.println("");
//Day 2
Serial.print(FCTimeD02);
Serial.print(" ");
Serial.print(FCTemp02);
Serial.print(" ");
Serial.print(FCTempL02);
Serial.print(" ");
Serial.print(FCHumid02);
Serial.print(" ");
Serial.print(FCWSpd02);
Serial.print(" ");
Serial.print(FCWDir02);
Serial.print(" ");
Serial.print(FCWGst02);
Serial.print(" ");
Serial.print(FCRain02);
Serial.print(" - ");
Serial.print(FCProb02);
Serial.print(" ");
Serial.print(FCSky02);
Serial.println("");
//Day 3
Serial.print(FCTimeD03);
Serial.print(" ");
Serial.print(FCTemp03);
Serial.print(" ");
Serial.print(FCTempL03);
Serial.print(" ");
Serial.print(FCHumid03);
Serial.print(" ");
Serial.print(FCWSpd03);
Serial.print(" ");
Serial.print(FCWDir03);
Serial.print(" ");
Serial.print(FCWGst03);
Serial.print(" ");
Serial.print(FCRain03);
Serial.print(" - ");
Serial.print(FCProb03);
Serial.print(" ");
Serial.print(FCSky03);
Serial.println("");
//Day 4
Serial.print(FCTimeD04);
Serial.print(" ");
Serial.print(FCTemp04);
Serial.print(" ");
Serial.print(FCTempL04);
Serial.print(" ");
Serial.print(FCHumid04);
Serial.print(" ");
Serial.print(FCWSpd04);
Serial.print(" ");
Serial.print(FCWDir04);
Serial.print(" ");
Serial.print(FCWGst04);
Serial.print(" ");
Serial.print(FCRain04);
Serial.print(" - ");
Serial.print(FCProb04);
Serial.print(" ");
Serial.print(FCSky04);
Serial.println("");
// Display the Forecast Values
DspForecast(9, 230, FCDOW00, FCTemp00, FCTempL00, FCHumid00, FCProb00, FCRain00); //Day 0 Current Days Forecast
DspForecast(167, 230, FCDOW01, FCTemp01, FCTempL01, FCHumid01, FCProb01, FCRain01); //Day 1 Forecast
DspForecast(325, 230, FCDOW02, FCTemp02, FCTempL02, FCHumid02, FCProb02, FCRain02); //Day 2 Forecast
DspForecast(483, 230, FCDOW03, FCTemp03, FCTempL03, FCHumid03, FCProb03, FCRain03); //Day 3 Forecast
DspForecast(641, 230, FCDOW04, FCTemp04, FCTempL04, FCHumid04, FCProb04, FCRain04); //Day 4 Forecast
}
}
void getSunriseSunset() {
Serial.println("\nStarting connection to server: api.openweathermap.org Sunrise/Sunset...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.print("GET /data/2.5/weather?");
//client.print("q="+location);
client.print("id="+location);
client.print("&appid="+apiKey);
client.print("&cnt=9");
client.println("&units=imperial"); // imperial= Fahrenheit, metric= Celsius,default is Kelvin
client.println("Host: api.openweathermap.org");
client.println("Connection: close");
client.println();
} else {
Serial.println("************************unable to connect************************");
client.stop();
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// unsuccessful, retry in 4 seconds
Serial.print("failed ... ");
delay(4000);
Serial.print("retrying ... ");
}
}
delay(1000);
String line = "";
while (client.connected()) {
line = client.readStringUntil('\n');
//Serial.println(line);
Serial.print("Line : "); Serial.println(line);
Serial.println("parsingValues");
//create a json buffer where to store the json data
StaticJsonBuffer<8000> jsonBuffer; //Arduinojson5
JsonObject& root = jsonBuffer.parseObject(line); //Arduinojson5
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
char loSrt[20];
char loSst[20];
//get the data from the json tree
//time_t srt = root["sys"]["sunrise"];
//root["sys"]["sunrise"] is UTC stringUtcToLocal is not working might be missing TZ info.
//["sys"]["sunrise"] is in UNIX Format
String Sunrs = root["sys"]["sunrise"];
time_t srt = Sunrs.toInt();
time_t locsrt = myTZ.toLocal(srt, &tcr);
makeHrMinTimeString(locsrt, loSrt);
strcpy(loSrt, DtTme); //Copy Global DtTime from makeTimeString to lo
String Sunst = root["sys"]["sunset"];
time_t sst = Sunst.toInt();
time_t locsst = myTZ.toLocal(sst, &tcr);
makeHrMinTimeString(locsst, loSst);
strcpy(loSst, DtTme);
// Print values.
Serial.print("SunRise ");
Serial.println(loSrt);
Serial.print("Sunset ");
Serial.println(loSst);
char curSunrise[32];
sprintf(curSunrise, "%02d:%02d", hour(locsrt), minute(locsrt));
char curSunset[32];
sprintf(curSunset, "%02d:%02d", hour(locsst), minute(locsst));
// Print values.
Serial.print("SunRise ");
Serial.println(curSunrise);
Serial.print("Sunset ");
Serial.println(curSunset);
// Display the Values
tft.graphicsMode();
tft.fillRect(9, 15, 150, 200, MEDTURQUOISE);
tft.textMode(); // go to text mode
tft.textSetCursor(20, 170);
tft.textTransparent(WHITE);
tft.textEnlarge(0);
tft.textWrite("Sunrise");
tft.textSetCursor(100, 170);
tft.textWrite(curSunrise);
//tft.setFont(&FreeSansBold24pt7b);
//void setCursor(uint16_t x0, uint16_t y0);
//void setTextColor(uint16_t color);
tft.textSetCursor(20, 190);
tft.textTransparent(WHITE);
tft.textWrite("Sunset");
tft.textSetCursor(100, 190);
tft.textWrite(curSunset);
tft.graphicsMode();
}
}
void DspForecast(int vstart, int hstart, char dow[10], char htemp[5], char ltemp[5], char hum[5], char prob[5], char moist[5]){
//Displays the forecast on display panel in five 150x135 turquose boxes with white lettering
tft.graphicsMode();
tft.fillRect((vstart), (hstart), 150, 135, MEDTURQUOISE);
tft.textMode(); // go to text mode
tft.textEnlarge(1);
tft.textTransparent(WHITE);
//line 227 For Day of the week / date
tft.textSetCursor((vstart-1),(hstart-3));
tft.textWrite(dow);
//line 255 for Hi and Lo Temperature
tft.textSetCursor((vstart-1),(hstart+25));
tft.textWrite("T");
tft.textSetCursor((vstart+3),(hstart+25));
tft.textWrite(htemp);
tft.textSetCursor((vstart+73),(hstart+25));
tft.textWrite("|");
tft.textSetCursor((vstart+63),(hstart+25));
tft.textWrite(ltemp);
//line 280 For Humidity
tft.textSetCursor((vstart-1),(hstart+50));
tft.textWrite("H");
tft.textSetCursor((vstart+3),(hstart+50));
tft.textWrite(hum);
tft.textSetCursor((vstart+101),(hstart+50));
tft.textWrite("%");
//line 305 Moisture
tft.textSetCursor((vstart-1),(hstart+75));
tft.textWrite("RS");
//tft.textSetCursor((vstart+3),(hstart+75));
tft.textSetCursor((vstart+13),(hstart+75));
tft.textWrite(prob);
//tft.textSetCursor((vstart+73),(hstart+75));
tft.textSetCursor((vstart+83),(hstart+75));
tft.textWrite("|");
//tft.textSetCursor((vstart+63),(hstart+75));
tft.textSetCursor((vstart+73),(hstart+75));
tft.textWrite(moist);
//line 330 For Wind Speed Direction and Gust
tft.textSetCursor((vstart-1),(hstart+100));
tft.textWrite("W");
}
// displays at startup the Sketch running in the Arduino
void display_Running_Sketch (void){
String the_path = __FILE__;
//int slash_loc = the_path.lastIndexOf('/');
int slash_loc = the_path.lastIndexOf('\\');
String the_cpp_name = the_path.substring(slash_loc+1);
int dot_loc = the_cpp_name.lastIndexOf('.');
String the_sketchname = the_cpp_name.substring(0, dot_loc);
Serial.print("\nArduino is running Sketch: ");
Serial.println(the_sketchname);
Serial.print("Compiled on: ");
Serial.print(__DATE__);
Serial.print(" at ");
Serial.println(__TIME__);
}