#include <RTClib.h>
#include <WiFi.h>
#include <PubSubClient.h>

#define WIFISSID "Wokwi-GUEST" // Put your WifiSSID here
#define PASSWORD "" // Put your wifi password here
#define TOKEN "BBUS-JsrzmMZ6qAe1wehA4TqqviD1u6kmWd" // Put your Ubidots' TOKEN
#define MQTT_CLIENT_NAME "RandomName" // MQTT client Name, please enter your own 8-12 alphanumeric character ASCII string; 
                                           //it should be a random and unique ascii string and different from all other devices

RTC_DS1307 rtc;

char daysOfWeek[7][12] = {
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday"
};

/****************************************
 * Define Constants
 ****************************************/
#define VARIABLE_LABEL_LAMPU "lampu" // Assing the variable label
#define VARIABLE_LABEL_WAKTU "waktu" // Assing the variable label
#define VARIABLE_LABEL "button" // Assing the variable label
#define VARIABLE_LABEL_SUBSCRIBE "led" // Assing the variable label
#define DEVICE_LABEL "esp32_andika_rtc" // Assig the device label

#define led 2
#define button 15

char mqttBroker[]  = "stem.ubidots.com";
char payload[1000];
char topic[150];
char topicSubscribe[100];
// Space to store values to send
char str_sensor[10];
char str_waktu[50];

/****************************************
 * Auxiliar Functions
 ****************************************/
WiFiClient ubidots;
PubSubClient client(ubidots);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.println("Attempting MQTT connection...");
    
    // Attemp to connect
    if (client.connect(MQTT_CLIENT_NAME, TOKEN, "")) {
      Serial.println("Connected");
      client.subscribe(topicSubscribe);
    } else {
      Serial.print("Failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 2 seconds");
      // Wait 2 seconds before retrying
      delay(2000);
    }
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  char p[length + 1];
  memcpy(p, payload, length);
  p[length] = NULL;
  String message(p);
  int menu=message.toInt(); //untuk konversi
  if (menu == 1) {
    digitalWrite(led, LOW);
  } else {
    digitalWrite(led, HIGH);
  }
  
  Serial.write(payload, length);
  Serial.println();
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello, ESP32!");

  // SETUP RTC MODULE
  if (! rtc.begin()) {
    Serial.println("RTC module is NOT found");
    Serial.flush();
    while (1);
  }

  // automatically sets the RTC to the date & time on PC this sketch was compiled
  //asal nya
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // DateTime now = rtc.now();
  // rtc.adjust(DateTime(2025,now.month(),now.day(),now.hour(),now.minute(),now.second()));

  // manually sets the RTC with an explicit date & time, for example to set
  // January 21, 2021 at 3am you would call:
  // rtc.adjust(DateTime(2021, 1, 21, 3, 0, 0));

  WiFi.begin(WIFISSID, PASSWORD);
  // Assign the pin as INPUT 
  pinMode(led, OUTPUT);
  
  Serial.println();
  Serial.print("Wait for WiFi...");

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  
  Serial.println("");
  Serial.println("WiFi Connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  client.setServer(mqttBroker, 1883);
  client.setCallback(callback);

  sprintf(topicSubscribe, "/v1.6/devices/%s/%s/lv", DEVICE_LABEL, VARIABLE_LABEL_SUBSCRIBE);
  
  client.subscribe(topicSubscribe);

}

void loop() {
  // put your main code here, to run repeatedly:
  //delay(10); // this speeds up the simulation

  DateTime now = rtc.now();
  //DateTime now = new DateTime();
  Serial.print("ESP32 RTC Date Time: ");
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.println(now.second(), DEC);

  //delay(1000); // delay 1 seconds

  //String time_ = now.year() + '/' + now.month() + '/' + now.day() ;

  // String time_ = String( (now.year(), DEC) + '/' + (now.month(), DEC) + '/' + (now.day(), DEC) );

  //String time_ = String( now.year() ) + "/" + String( now.month() ) + "/" + String( now.day() ) + " " + String( now.hour() ) + ":" + String( now.minute() ) + ":" + String( now.second() );
  String time_ = String( now.year() ) + "/" + String( now.month() ) + "/" + String( now.day() ) ;
  // lcd.setCursor(0, 0); // Or setting the cursor in the desired position.
  // lcd.println(time_);

  String time__ = String( now.hour() ) + ":" + String( now.minute() ) + ":" + String( now.second() );
  // lcd.setCursor(0, 1); // Or setting the cursor in the desired position.
  // lcd.println(time__);

  delay(1000);
  //lcd.clear();

  if (!client.connected()) {
    client.subscribe(topicSubscribe);   
    reconnect();
  }

  //jika detik gajil maka lampu nyala
  sprintf(topic, "%s%s", "/v1.6/devices/", DEVICE_LABEL);
  sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "{\"%s\":", VARIABLE_LABEL_LAMPU); // Adds the variable label
  
  //jika detik gajil maka lampu nyala
  float Logicsensor = 0;
  if( now.second() % 2 != 0 ){
    Logicsensor = 1;
    digitalWrite(led, LOW); //lampu di arduino menyala
  }else{
    Logicsensor = 0;
    digitalWrite(led, HIGH); //lampu di arduino mati
  }

  Serial.print("Value of Sensor is:- ");
  Serial.println(Logicsensor);
  
  /* 4 is mininum width, 2 is precision; float value is copied onto str_sensor*/
  dtostrf(Logicsensor, 4, 2, str_sensor);
  
  // sprintf(payload, "%s {\"value\": %s}}", payload, str_sensor); // Adds the value
  sprintf(payload, "%s {\"value\": %s}", payload, str_sensor); // Adds the value
  Serial.println("Publishing data to Ubidots Cloud");

  //add valriable waktu
  //String waktu = String( now.year() ) + "/" + String( now.month() ) + "/" + String( now.day() ) + "" + String( now.hour() ) + ":" + String( now.minute() ) + ":" + String( now.second() );
  String waktu = String( now.second() );
  waktu.toCharArray(str_waktu, 50);
  //sprintf(payload, "%s", ""); // Cleans the payload
  sprintf(payload, "%s%s", payload,","); // Cleans the payload
  sprintf(payload, "%s \"%s\":", payload, VARIABLE_LABEL_WAKTU); // Adds the variable label
  sprintf(payload, "%s {\"value\": %s}}", payload, str_waktu); // Adds the value
  //end add valriable waktu
  Serial.println("cek : ");
  Serial.println(payload);

  //send multiple variable
  client.publish(topic, payload);
  client.loop();

  delay(5000);

}
GND5VSDASCLSQWRTCDS1307+