#include <Adafruit_GFX.h>     //~/Documents/Arduino/libraries/Adafruit_ST7735_and_ST7789_Library/Adafruit_ST7735.cpp
#include <Adafruit_ST7735.h>  //if statement: displayInit(Rcmd3); setColRowStart(2, 1); //   displayInit(Rcmd3);
#include <WiFi.h>
#include <NTPClient.h>
#include <Wire.h>
#include <WiFiUdp.h>
#include <AHT20.h>
#include <Adafruit_BMP280.h>
#include <Arduino_JSON.h>
#include <WiFiClient.h>
#include <HTTPClient.h>
#include "ThingSpeak.h"
#include "credentials.h"  // Include the credentials header file

#define SENSOR 27
#define TFT_CS 5
#define TFT_RST -1
#define TFT_DC 15

Adafruit_BMP280 bmp;
AHT20 aht20;
const char *serverName = "api.thingspeak.com/update";
unsigned long elapsedSeconds = 0;
unsigned long startTime;                                // Start time for sensor timing
unsigned long lastWeatherUpdateTime = 0;                // Last time weather data was updated
unsigned long lastThingSpeakUpdateTime = 0;             // Last time ThingSpeak fields were updated
unsigned long lastPrintTime = 0;                        // Last time sensor elapsed time was printed
unsigned long lastNTPUpdateTime = 0;                    // Last time NTP client time was updated
unsigned long lastScreenChangeTime = 0;                 // Last time the screen was changed
unsigned long totalElapsedTime = 0;
unsigned long lastFlowScreenUpdate = 0;
unsigned long lastCheckTime = 0;
const unsigned long flowScreenInterval = 1000; // Update the flow screen every 1s // Total elapsed time for sensor timing
const unsigned long screenChangeInterval = 12000;       // Interval for screen change in milliseconds
const unsigned long weatherUpdateInterval = 3600000;     // Interval between weather updates (1 hours)
const unsigned long thingSpeakUpdateInterval = 7202000;  // Interval for updating ThingSpeak fields (2 hours)
const unsigned long checkInterval = 10802000; // 3 hours in milliseconds for weekday
bool timing = false;                                    // Flag to indicate whether timing is active
// Global variables to keep track of elapsed time in seconds and the last update time
unsigned long elapsedTime = 0;
unsigned long lastUpdate = 0;
volatile unsigned long lastPulseTime = 0;
const unsigned long debounceTime = 30; // Debounce time for flowmeter. It is better resistor and a capacitor
const int sensorPin = SENSOR;
const int rainLed = 2;   // Indicates rain
const int clearLed = 0;  // Indicates clear sky or sunny
const int cloudLed = 4;  // Indicates cloud
const int noLed = 13;  // Indicates system will not water

String formattedTime = "";
String currentDate = "";
String lastCheckedDate = "";  // Store the last checked date for reset
String weatherCondition = "";
String compassDirection = "";
String directions = "";
WiFiClient client;
String jsonBuffer;
String httpGETRequest(const char *serverName);

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
String city = "Archanes";
String countryCode = "GR";
unsigned long myChannelNumber = 2514774;
const int FieldNumber1 = 5;
const int FieldNumber2 = 8;  // The field you wish to read

String weekdays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
int currentWeekday;
//String months[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
int currentScreen = 0;  // Variable to track the current screen
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
float temp;  // get temperature in °C
float humi;  // get humidity in %
float pres;
float windSpeed;
float windDirection;
long currentMillis = 0;
long previousMillis = 0;
int interval = 1000;//flowmeter read time
float calibrationFactor = 4.5;
volatile byte pulseCount;
byte pulse1Sec = 0;
float flowRate;
float maxFlowRate;//max
float elapsedTimeMinutes;
float elapsedTimeHours = 0.0;
unsigned long flowMilliLitres;
unsigned int totalMilliLitres;
float flowLitres;
float totalLitres;
void IRAM_ATTR pulseCounter();

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  ThingSpeak.begin(client);
  pinMode(clearLed, OUTPUT);
  pinMode(rainLed, OUTPUT);
  pinMode(cloudLed, OUTPUT);
  pinMode(noLed, OUTPUT);

  // Initialize TFT display
  tft.initR(INITR_BLACKTAB);
  tft.setTextWrap(false);
  tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_RED, ST7735_BLACK);
  WiFi.begin(ssid, password);

  // Initialize NTP Client to get time
  timeClient.begin();
  timeClient.setTimeOffset(10800);
  
  // INITIALIZE Screen
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  tft.setTextSize(2);
  tft.setCursor(0, 5);
  tft.print("MADE BY KN");
  tft.setCursor(40, 10);
  tft.print("");
  tft.setTextSize(1, 3);
  tft.setCursor(5, 70);
  tft.print("Connecting...");
  lastScreenChangeTime = millis();

  Wire.begin();
  if (aht20.begin() == false) {
    Serial.println("AHT20 not detected. Please check wiring. Freezing.");
    while (1);
  } else {
    Serial.println("AHT20 acknowledged");
    tft.setTextSize(2);
    tft.setCursor(5, 30);
    tft.print("AHT OK");
    // Optionally, you could exit or take other actions if connection failed
  }
  unsigned status;
  status = bmp.begin();
  if (!bmp.begin()) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    while (1);
  } else {
    Serial.println("BMP280 acknowledged");
    tft.setTextSize(2);
    tft.setCursor(5, 50);
    tft.print("BMP280 OK");
    // Optionally, you could exit or take other actions if connection failed
  }
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

  pinMode(SENSOR, INPUT_PULLUP);
  pulseCount = 0;
  flowRate = 0.0;
  maxFlowRate = 0.0;//max
  flowMilliLitres = 0;
  totalMilliLitres = 0;
  previousMillis = 0;
  attachInterrupt(digitalPinToInterrupt(SENSOR), pulseCounter, RISING);

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Attempting to connect to WiFi...");
    WiFi.begin(ssid, password);
    ThingSpeak.begin(client);
    while (WiFi.status() != WL_CONNECTED) {
      delay(250);
      Serial.print(".");
    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("Connected to WiFi.");
      tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
      tft.setTextSize(2);
      tft.setCursor(5, 100);
      tft.print("WiFi OK");
      printWifiStatus();
      delay(5000);
    } else {
      Serial.println("Failed to connect to WiFi.");
    }
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Updating totalLitres and total elapsed time...");
    long ThTL = readTLData();
    float ThET = readETData();
    totalLitres = ThTL;
    elapsedTimeHours =ThET;
    //totalElapsedTime = ThET * 3600000;  // Convert hours to milliseconds
    //elapsedTimeHours = totalElapsedTime / 3600000.0;  // Update global elapsedTimeHours
  } else {
    Serial.println("WiFi is not connected. Cannot update totalLitres and elapsed time.");
  }
}

void pulseCounter() {
  unsigned long currentPulseTime = millis();
  if (currentPulseTime - lastPulseTime > debounceTime) {
    pulseCount++;
    lastPulseTime = currentPulseTime;
  }
}

void loop() {
  currentMillis = millis();
  // Flow rate and timing section
  if (flowRate > 0.1) {
    //flowscreen();  // Continuously call flowscreen
    if (!timing) {
      startTime = currentMillis;
      timing = true;
      elapsedTime = 0;  // Reset elapsed time when flow resumes
      Serial.println("Timing started");
    }
    // Update the flow screen at intervals to reduce flickering
    if (currentMillis - lastFlowScreenUpdate >= flowScreenInterval) {
      flowscreen();
      lastFlowScreenUpdate = currentMillis;
    }

  } else {
    if (timing) {
      unsigned long endTime = currentMillis;
      unsigned long elapsedTime = endTime - startTime;
      timing = false;
      totalElapsedTime += elapsedTime;
      elapsedTimeHours = totalElapsedTime / 3600000.0; // Update elapsedTimeHours
      updateTFTDisplay(totalElapsedTime);
      Serial.println("Timing stopped and display updated");
      Serial.print(totalElapsedTime / 60000.0, 2);  // Convert ms to minutes and print with two decimal places
      Serial.println(" min");
    }
  }
  // Print elapsed time every second while timing is active
  if (timing && (currentMillis - lastPrintTime) >= 1000) {
    elapsedSeconds = (currentMillis - startTime) / 1000;  // Elapsed time in seconds
    Serial.print("Elapsed time: ");
    Serial.print(elapsedSeconds);
    Serial.println(" seconds");
    lastPrintTime = currentMillis;
  }

  // Other periodic tasks
  // Weather update section
  if ((currentMillis - lastWeatherUpdateTime) >= weatherUpdateInterval) {
    lastWeatherUpdateTime = currentMillis;
    updateWeather();
  }

  // Time and date update section
  if ((currentMillis - lastNTPUpdateTime) >= screenChangeInterval) {
    lastNTPUpdateTime = currentMillis;
    updateTimeAndDate();
  }

  // Screen change section
  if (flowRate <= 0.1 &&(currentMillis - lastScreenChangeTime) >= screenChangeInterval) {
    lastScreenChangeTime = currentMillis;
    changeScreen();
  }
   // Check if the date has changed every 12Hrs
  if (currentMillis - lastCheckTime >= checkInterval) {
   if (currentDate != lastCheckedDate) {
    // Reset totalMilliLitres and maxFlowRate at midnight
    totalMilliLitres = 0;
    maxFlowRate = 0.0;
    lastCheckedDate = currentDate;
    Serial.print("Date changed at "+ weekdays[currentWeekday]+".Resetting totalMilliLitres and maxFlowRate.");
    lastCheckTime = currentMillis;
    }
   }
  // ThingSpeak update section
  if ((currentMillis - lastThingSpeakUpdateTime) > thingSpeakUpdateInterval) {
    // Check Wi-Fi connection before attempting to update ThingSpeak
    if (WiFi.status() == WL_CONNECTED) {
      ThingSpeak.begin(client);
      updateThingSpeakFields();
    } else {
      Serial.print("WiFi not connected. Skipping ThingSpeak update.");
    }
    lastThingSpeakUpdateTime = currentMillis;
  }

  // Sensor data update section
  updateSensorData();
}

void updateWeather() {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&APPID=" + openWeatherMapApiKey;
    String jsonBuffer = httpGETRequest(serverPath.c_str());
    //Serial.println(jsonBuffer);
    JSONVar weatherData = JSON.parse(jsonBuffer);

    if (JSON.typeof(weatherData) == "undefined") {
      Serial.println("Failed to parse weather data!");
      return;
    }
    Serial.print("Weather data: ");
    Serial.print(weatherData);
    windSpeed = (int)weatherData["wind"]["speed"];
    windDirection = (int)weatherData["wind"]["deg"];
    weatherCondition = String((const char *)weatherData["weather"][0]["main"]);

    Serial.print("Wind Speed : ");
    Serial.println(windSpeed);
    Serial.print("Wind Direction: ");
    Serial.println(windDirection);
    Serial.print("Weather: ");
    Serial.println(weatherCondition);
    Serial.print("Channel update successful at "+ formattedTime +".");

    if (weatherCondition.equals("Rain") || weatherCondition.equals("Thunderstorm") || weatherCondition.equals("Snow") || weatherCondition.equals("Fog") || weatherCondition.equals("Drizzle")) {
      digitalWrite(rainLed, HIGH);
      digitalWrite(noLed, HIGH);
      Serial.print("noLed, ON - ");
      digitalWrite(clearLed, LOW);
      digitalWrite(cloudLed, LOW);
      Serial.print("rainLed, ON - ");
    } else if (weatherCondition.equals("Clouds")) {
      digitalWrite(cloudLed, HIGH);
      digitalWrite(rainLed, LOW);
      digitalWrite(clearLed, LOW);
      Serial.print("cloudLed, ON - ");
      // Check if the temperature is below 15°C
        if (temp < 18) {
          digitalWrite(noLed, HIGH);
          Serial.print("noLed, ON - ");
         } else {
          digitalWrite(noLed, LOW);
          Serial.print("noLed, OFF - ");
         }
    } else {
      digitalWrite(rainLed, LOW);
      digitalWrite(clearLed, HIGH);
      digitalWrite(cloudLed, LOW);
      Serial.print("clearLed, ON - ");
    }
  }
}

void updateTFTDisplay(unsigned long elapsedTimeMillis) {
  float elapsedTimeMinutes = elapsedTimeMillis / 60000.0;
  Serial.print("totalElapsedTime: ");
  Serial.print(elapsedTimeMinutes, 2);
  Serial.println(" min");
}

void updateThingSpeakFields() {
  Serial.print((int)temp);
  Serial.print((int)humi);
  Serial.print((int)pres / 100);
  Serial.print((int)flowLitres);
  Serial.print((int)totalLitres);
  Serial.print((int)windSpeed);
  Serial.print((int)windDirection);
  ThingSpeak.setField(1, (int)temp);
  ThingSpeak.setField(2, (int)humi);
  ThingSpeak.setField(3, (int)pres / 100);
  ThingSpeak.setField(4, (int)maxFlowRate);
  ThingSpeak.setField(5, (int)totalLitres);
  ThingSpeak.setField(6, (int)windSpeed);
  ThingSpeak.setField(7, (int)windDirection);
  ThingSpeak.setField(8, (elapsedTimeHours));
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  if (x == 200) {
    Serial.print("Channel update successful at "+ formattedTime +".");
  } else {
    Serial.print("Problem updating channel. HTTP error code " + String(x));
  }
}

void updateTimeAndDate() {
  // Update time
  timeClient.update();
  // Get current time
  formattedTime = getFormattedTime();
  // Get current date
  currentDate = getCurrentDate();
}

String getFormattedTime() {
  // Get current hour and minute
  int currentHour = timeClient.getHours();
  int currentMinute = timeClient.getMinutes();
  // Format time
  String formattedHour = String(currentHour);
  String formattedMinute = String(currentMinute);
  if (currentMinute < 10) {
    formattedMinute = "0" + formattedMinute;  // prepend a zero if minute is single digit
  }
  return formattedHour + ":" + formattedMinute;
}

String getCurrentDate() {
  // Get current date
  time_t epochTime = timeClient.getEpochTime();
  struct tm *ptm = gmtime((time_t *)&epochTime);
  int currentWeekday = (epochTime / 86400L + 4) % 7; // Calculate weekday (0 for Sunday)
  int monthDay = ptm->tm_mday;
  int currentMonth = ptm->tm_mon + 1;
  int currentYear = ptm->tm_year + 1900;
  // Format date
  return String(monthDay) + "-" + String(currentMonth) + "-" + String(currentYear);
}

void updateSensorData() {
  // Update temperature, humidity, pressure
  temp = aht20.getTemperature();  // get temperature in °C
  humi = aht20.getHumidity();     // get humidity in %
  pres = bmp.readPressure();      // get pressure in Pa
  // Update flow rate
  updateFlowRate();
}

void updateFlowRate() {
  currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    pulse1Sec = pulseCount;
    pulseCount = 0;
    flowRate = ((1000.0 / (currentMillis - previousMillis)) * pulse1Sec) / calibrationFactor;
    previousMillis = currentMillis;
    flowMilliLitres = (flowRate / 60.0) * 1000.0;
    flowLitres = flowRate / 60.0;
    totalMilliLitres += flowMilliLitres;
    totalLitres += flowLitres;
    // Print flow rate and total litres
    // Update the maximum flow rate if the current flow rate is higher
  if (flowRate > maxFlowRate) {
    maxFlowRate = flowRate;
  }
    Serial.print("Flow rate: ");
    Serial.print(flowRate);
    Serial.println(" L/min");
    Serial.print("Max Flow rate: ");
    Serial.print(maxFlowRate);
    Serial.println(" L/min");
    Serial.print("Daily Quantity: ");
    Serial.print(totalMilliLitres/1000.0);
    Serial.println(" L");
    Serial.print("Total: ");
    Serial.print(totalLitres);
    Serial.println(" L");
  }
}

void flowscreen() {
  tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  tft.setTextSize(2);
  tft.setCursor(15, 10);
  tft.print("POTISMA");
  tft.setCursor(5, 35);
  tft.print((int)flowRate);
  tft.println(" L/min");
  tft.setCursor(5, 60);
  tft.print((int)totalMilliLitres / 1000);
  tft.println(" L");
  tft.setCursor(5, 90);
  tft.print("Time: ");
  tft.setCursor(5, 120);
  tft.print(elapsedSeconds);
  tft.println(" sec");
}

void changeScreen() {
  // Increment current screen
  currentScreen++;
  currentScreen %= 3;  // adjust to the number of screens you have
  // Clear the screen
  tft.fillScreen(ST7735_BLACK);
  // Display the new screen
  switch (currentScreen) {
    case 0:
      // Display time screen
      displayScreen0();
      break;
    case 1:
      // Display water time screen
      displayScreen1();
      break;
    case 2:
      // Display sensor data screen
      displayScreen2();
      break;
    default:
      // Default case: if currentScreen is out of range, reset it to 0
      currentScreen = 0;
      break;
  }
}

void displayScreen0() {
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  tft.setCursor(5, 5);
  tft.setTextSize(2);
  tft.print("Max Flow");
  tft.setCursor(15, 30);
  tft.print(maxFlowRate, 1);
  tft.println(" L/m");
  tft.setCursor(8, 55);
  tft.println("Daily Qty");
  tft.setCursor(15, 80);
  tft.print(totalMilliLitres / 1000);
  tft.println(" L");
  tft.drawFastHLine(0, 100, tft.width(), ST7735_WHITE);  // draw horizontal white line 
  tft.setCursor(38, 110);
  tft.print(formattedTime);
  tft.setCursor(10, 135);
  tft.print(currentDate);
}

void displayScreen1() {
  float elapsedTimeHours = totalElapsedTime / 3600000.0;
  Serial.print("total Hours: ");
  Serial.print(elapsedTimeHours);
  Serial.println(" hrs");
  tft.setTextSize(1.5);  // text size
  tft.setCursor(0, 4);   // move cursor to position
  tft.print("Total Time");
  tft.setTextSize(1.5);  // text size
  tft.setCursor(70, 4);  // move cursor to position (5, 76) pixel
  tft.print("Total Ltrs");
  tft.drawFastHLine(0, 47, tft.width(), ST7735_WHITE);  // draw horizontal white line
  tft.drawFastVLine(67, -80, tft.width(), ST7735_WHITE);
  //tft.setTextColor(ST7735_WHITE, ST7735_BLACK);  // set text color to white and black background
  tft.setTextSize(1);
  tft.drawFastHLine(0, 90, tft.width(), ST7735_WHITE);   // draw horizontal white line
  tft.drawFastHLine(0, 125, tft.width(), ST7735_WHITE);  // draw horizontal white line
  tft.setTextColor(ST7735_RED, ST7735_BLACK);            // set text color to red and black background
  tft.setCursor(25, 54);                                 // move cursor to position
  tft.print("TEMPERATURE");
  tft.setTextColor(ST7735_CYAN, ST7735_BLACK);  // set text color to cyan and black background
  tft.setCursor(34, 94);                        // move cursor to position
  tft.print("HUMIDITY");
  tft.setTextColor(ST7735_GREEN, ST7735_BLACK);  // set text color to green and black background
  tft.setCursor(34, 131);                        // move cursor to position
  tft.print("PRESSURE");
  tft.setTextSize(2);  // text size
  // print °C
  tft.drawCircle(89, 70, 2, ST7735_YELLOW);       // print degree symbol ( ° )
  tft.setCursor(95, 70);                          // move cursor to position
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);  // set text color to yellow and black background
  tft.print("C");
  tft.setCursor(91, 146);
  tft.print("hPa");
  tft.setCursor(3, 24);
  tft.setTextColor(0xFD00, ST7735_BLACK);  // set text color to orange and black background
  tft.printf("%03u.%01u", (int)elapsedTimeHours, (int)(elapsedTimeHours * 10.0f) % 10);
  tft.setCursor(78, 24);
  tft.setTextColor(0xFD00, ST7735_BLACK);  // set text color to orange and black background
  tft.printf("%04u", (int)totalLitres, (int)(totalLitres * 100) % 100);
  // print data on the display
  // 1:print temperature (in °C)
  tft.setCursor(11, 70);
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);  // set text color to yellow and black background
  if (temp < 0)                                   // if temperature < 0
    tft.printf("-%02u.%02u", (int)abs(temp), (int)(abs(temp) * 100) % 100);
  else  // temperature >= 0
    tft.printf(" %02u.%02u", (int)temp, (int)(temp * 100) % 100);
  // 2: print humidity
  tft.setCursor(23, 108);
  tft.setTextColor(ST7735_MAGENTA, ST7735_BLACK);  // set text color to magenta and black background
  tft.printf("%02u.%02u %%", (int)humi, (int)(humi * 100) % 100);
  // 3: print pressure (in hPa)
  tft.setCursor(3, 146);
  tft.setTextColor(0xFD00, ST7735_BLACK);  // set text color to orange and black background
  tft.printf("%04u.%02u", (int)(pres / 100), (int)((uint32_t)pres % 100));
}

void displayScreen2() {
  compassDirection = getCompassDirection(windDirection);
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  tft.setTextSize(2);
  tft.setCursor(8, 5);
  tft.print("Wind Speed");
  tft.setCursor(8, 25);
  tft.print((int)windSpeed);
  tft.println(" knots");
  tft.setCursor(8, 50);
  tft.print("Direction");
  tft.setCursor(4, 75);
  tft.print((int)windDirection);
  tft.println("deg");
  tft.setCursor(90, 75);
  tft.print(compassDirection);
  tft.setCursor(8, 100);
  tft.print("Weather");
  tft.setCursor(8, 125);
  tft.print(weatherCondition);
}

void printWifiStatus() {
  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  tft.setTextSize(1.8);
  tft.setCursor(10, 125);
  tft.print(WiFi.SSID());
  tft.setCursor(10, 135);
  tft.print(WiFi.localIP());
  tft.setCursor(10, 145);
  tft.print(WiFi.RSSI());
  tft.println(" dBm");
}

String getCompassDirection(int windDirection) {
    String directions[] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", 
                           "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N"};
    int idx = round(windDirection / 22.5);
    return directions[idx % 16];
    /*If you want show you only two letters then 
    String directions[] = {"N", "NE", "E", "SE", 
                           "S", "SW", "W", "NW", "N"};
    int idx = round(windDirection / 45);
    return directions[idx % 8];*/
}

String httpGETRequest(const char *serverName) {
  HTTPClient http;
  http.begin(serverName);
  int httpResponseCode = http.GET();
  String payload = "{}";
  if (httpResponseCode > 0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  } else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  http.end();
  return payload;
}

long readTLData() {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    ThingSpeak.begin(client);
    long totalLitres = ThingSpeak.readLongField(myChannelNumber, FieldNumber1, myReadAPIKey);
    if (totalLitres == 0) {
      Serial.println("litres has been reset");
    } else {
      Serial.print("Total Litres from ThingSpeak: ");
      Serial.println(totalLitres);
    }
    return totalLitres;
  } else {
    Serial.println("WiFi is not connected.");
    //return 0;
  }
}
float readETData() {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    ThingSpeak.begin(client);
    float elapsedTimeHours = ThingSpeak.readFloatField(myChannelNumber, FieldNumber2, myReadAPIKey);
    if ( elapsedTimeHours == 0.0) {
      Serial.println("Time has been reset");
    } else {
      Serial.print("ElapsedTime from ThingSpeak: ");
      Serial.println(elapsedTimeHours);
    }
    return elapsedTimeHours;
  } else {
    Serial.println("WiFi is not connected.");
    //return 0;
  }
}