//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#include <PubSubClient.h>
#include <WiFi.h>
#include <ThingSpeak.h>


#ifdef USESECUREMQTT
  #include <WiFiClientSecure.h>
  #define mqttPort 8883
  WiFiClientSecure client; 
#else
  #define mqttPort 1883
  WiFiClient espClient;
#endif
//#define led 35
#define DHTPIN 14
#define DHTTYPE DHT22

const char* ssid = "Wokwi-GUEST";
const char* password = "";

// MQTT THINGSPEAK INFO
const char* mqttServer = "mqtt3.thingspeak.com";
const char mqttUserName[] = "IC4eDCo4IjscHgkUFy84CBQ"; 
const char clientID[] = "IC4eDCo4IjscHgkUFy84CBQ";
const char mqttPass[] = "kresMXXl2n8FaOEE9ZjY7dS2";

// API ThingSpeak information
char* server = "api.thingspeak.com";
unsigned long channelID = 2316231;
char* readAPIKey = "E4V0A6H7YXX09ZC3";
unsigned int dataField = 1;   

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display
PubSubClient mqttClient(espClient);


//declare
long lastPublishMillis = 0;
int connectionDelay = 1;
int updateInterval = 2;

float readData = 0;
void setup()
{
  // pinMode(led, OUTPUT);
  Serial.begin(9600);
  setup_wifi();  
  dht.begin();
  lcd.init();                      // initialize the lcd 
  // Print a message to the LCD.
  lcd.backlight();
  mqttClient.setServer( mqttServer, mqttPort ); 
  //readData = readThingspeakData( channelID, dataField );
  //delay(1000);

}


void loop()
{
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  lcd.setCursor(0,0);
  lcd.print("Temp: ");
  lcd.print(t);
  lcd.print(char(223));
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("Humidity: ");
  lcd.print(h);
  lcd.print("%");
  if (!mqttClient.connected()) 
  {
     mqttConnect();
  }

  // Call the loop to maintain connection to the server.
  mqttClient.loop();   

  // Update ThingSpeak channel periodically. The update results in the message to the subscriber.
  if ( abs(long(millis()) - lastPublishMillis) > updateInterval*1000) 
  {
    String payload = "field1=" + String(t) + "&" + "field2=" + String(h);
    mqttPublish( channelID, payload );
    lastPublishMillis = millis();
    // Serial.print("payload published to thingspeak, Temperature is ");
    // Serial.print(t);
    // Serial.println();
    // Serial.print("payload published to thingspeak, Humidity is ");
    // Serial.print(h);
    // Serial.println();
  }
  //reading data from thingspeak with api key
  float data = ThingSpeak.readFloatField(channelID, dataField, readAPIKey);
  
  Serial.print("Field ");
  Serial.print(dataField);
  Serial.print(": ");
  Serial.println(data);   
  delay(2000);

    // reading data from thingspeak with http GET request URL
    // String url = "/channels/" + String(channelID) + "/fields/" + String(fieldNumber) + ".json?api_key=" + apiKey + "&results=" + String(results);

    // // Make a GET request to ThingSpeak
    // if (client.connect(server, port)) {
    //   client.print(String("GET ") + url + " HTTP/1.1\r\n" +
    //                "Host: " + server + "\r\n" +
    //                "Connection: close\r\n\r\n");

    //   while (client.connected() || client.available()) {
    //     if (client.available()) {
    //       char c = client.read();
    //       Serial.print(c);
    //     }
    //   }
    //   Serial.println();
    //   client.stop();
    // } else {
    //   Serial.println("Failed to connect to ThingSpeak");
    // }

}
void setup_wifi() 
{
  delay(100);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  ThingSpeak.begin(espClient);

  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}


// Publish messages to a ThingSpeak channel.
void mqttPublish(long pubChannelID, String message) 
{
  String topicString ="channels/" + String( pubChannelID ) + "/publish";
  mqttClient.publish( topicString.c_str(), message.c_str() );
}

void mqttConnect() 
{
  // Loop until connected.
  while ( !mqttClient.connected() )
  {
    // Connect to the MQTT broker.
    if ( mqttClient.connect( clientID, mqttUserName, mqttPass ) ) 
    {
      Serial.print( "MQTT to " );
      Serial.print( mqttServer );
      Serial.print (" at port ");
      Serial.print( mqttPort );
      Serial.println( " successful." );
    } 
    else 
    {
      Serial.print( "MQTT connection failed, rc = " );
      // See https://pubsubclient.knolleary.net/api.html#state for the failure code explanation.
      Serial.print( mqttClient.state() );
      Serial.println( " Will try again in a few seconds" );
      delay( connectionDelay*1000 );
    }
  }
}
// Subscribe to ThingSpeak channel for updates.
// void mqttSubscribe( long subChannelID ){
//   String myTopic = "channels/"+String( subChannelID )+"/subscribe";
//   mqttClient.subscribe(myTopic.c_str());
// }