#include <WiFi.h> // WiFi control for ESP32
#include <ThingsBoard.h> // ThingsBoard SDK

// Helper macro to calculate array size
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
int quant = 20;

// WiFi access point
#define WIFI_AP_NAME "Wokwi-GUEST"

// WiFi password
#define WIFI_PASSWORD ""
int send_passed = 0;

// See https://thingsboard.io/docs/getting-started-guides/helloworld/
// to understand how to obtain an access token
#define TOKEN "Dyik7w4zpVBNAJjFgRtr"

// ThingsBoard server instance.
#define THINGSBOARD_SERVER "thingsboard.cloud"
int send_delay = 2000;

// Baud rate for debug serial
#define SERIAL_DEBUG_BAUD 115200

const int trigPin = 14;
const int echoPin = 27;
bool subscribed = false;

// defines variables
long duration;
int distance;

// Initialize ThingsBoard client
WiFiClient espClient;

// Initialize ThingsBoard instance
ThingsBoard tb(espClient);
int status = WL_IDLE_STATUS;

#define pinServoPakan 23
// #define ledMerah 34
// #define ledKuning 35
// #define ledHijau 32
   
#define waktuBukaServo  1000  //milidetik
#define servoBuka   45  //derajat
#define servoTutup  0   //derajat
   
#define waktuMakan1   DateTime(0, 1, 1,  8, 0, 0, 0) //jam 8 pagi
#define waktuMakan2   DateTime(0, 1, 1, 16, 0, 0, 0)  //jam 4 sore
#define waktuMakan3   DateTime(0, 1, 1,  24, 0, 0, 0) //jam 12 malam
   
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "Sodaq_DS3231.h"
#include <Servo.h>
   
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo servoPakanIkan;
   
byte detikSebelumnya;
char buf[17];

void setup() {
// Initialize serial for debugging
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
// pinMode(ledMerah, OUTPUT);
// pinMode(ledKuning, OUTPUT);
// pinMode(ledHijau, OUTPUT);
Serial.begin(SERIAL_DEBUG_BAUD);
Serial.print("Connecting to: "); Serial.println(WIFI_AP_NAME);
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected\n");

Serial.begin(9600);
  Serial.println("Pakan ikan otomatis");
     
  servoPakanIkan.attach(pinServoPakan);
  servoPakanIkan.write(servoTutup);
   
  Wire.begin();
  rtc.begin();
  // DateTime dt(2011, 11, 10, 15, 18, 0, 5); // set tanggal dan waktu (format): tahun, bulan tanggal, jam, menit, detik, hari (1=minggu, 7=sabtu)
  // rtc.setDateTime(dt);
   
  Wire.beginTransmission(0x3F);
  if (Wire.endTransmission())
  {
    lcd = LiquidCrystal_I2C(0x27, 16, 2);
  }
  
  lcd.init();
  lcd.backlight();
   
  lcd.print("Pemberi Pakan");
  lcd.setCursor(0, 1);
  lcd.print("Ikan Otomatis");
  delay(3000);
  lcd.clear();
   
  Serial.println("Sistem Pakan Otomatis Mulai");
  sprintf(buf, "Set waktu 1 = %02d:%02d (%lu)", waktuMakan1.hour(), waktuMakan1.minute(), waktuMakan1.get());
  Serial.println(buf);
  sprintf(buf, "Set waktu 2 = %02d:%02d (%lu)", waktuMakan2.hour(), waktuMakan2.minute(), waktuMakan2.get());
  Serial.println(buf);
   sprintf(buf, "Set waktu 3 = %02d:%02d (%lu)", waktuMakan3.hour(), waktuMakan3.minute(), waktuMakan3.get());
  Serial.println(buf);

}

void loop() {
send_passed += quant;
delay(quant);

// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);

// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);

// Calculating the distance
distance= duration*0.034/2;

// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);
if (WiFi.status() != WL_CONNECTED) {
return;
}
if (!tb.connected()) {
subscribed = false;

// Connect to the ThingsBoard
Serial.print("Connecting to: ");
Serial.print(THINGSBOARD_SERVER);
Serial.print(" with token ");
Serial.println(TOKEN);
if (!tb.connect(THINGSBOARD_SERVER, TOKEN)) {
Serial.println("Failed to connect");
return;
}
}

if (send_passed > send_delay) {
Serial.println("Sending data...");

// Uploads new telemetry to ThingsBoard using MQTT.
// See https://thingsboard.io/docs/reference/mqtt-api/#telemetry-upload-api
// for more details

tb.sendTelemetryFloat("distance", distance);
send_passed = 0;
}

// Process messages
tb.loop();

DateTime now = rtc.now();
  if (detikSebelumnya != now.second())
  {
    sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    lcd.setCursor(4, 0);
    lcd.print(buf);
    // Serial.print(buf);
   
    detikSebelumnya = now.second();
   
    uint32_t epoch = now.get() % 86400;   //hanya jam menit detik
   
    if ((epoch == waktuMakan1.get()) ||
        (epoch == waktuMakan2.get()) ||
        (epoch == waktuMakan3.get()))
    {
      char buf[17];
      sprintf(buf, "Pakan = %02d:%02d", now.hour(), now.minute());
      lcd.setCursor(0, 1);
      lcd.print(buf);
      // Serial.println(buf);
   
      servoPakanIkan.write(servoBuka);
      delay(waktuBukaServo);
      servoPakanIkan.write(servoTutup);
   
    }
  }

// if (distance > 25) {
//     digitalWrite(ledMerah, HIGH);
//     digitalWrite(ledKuning, LOW);
//     digitalWrite(ledHijau, LOW);
//   }
// else if (distance >= 3 && distance <= 25) {
//     digitalWrite(ledMerah, LOW);
//     digitalWrite(ledKuning, HIGH);
//     digitalWrite(ledHijau, LOW);
//   }
// else if (distance < 3) {
//     digitalWrite(ledMerah, LOW);
//     digitalWrite(ledKuning, LOW);
//     digitalWrite(ledHijau, HIGH);
//   }

}

void InitWiFi()
{
Serial.println("Connecting to AP ...");
// attempt to connect to WiFi network

WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}

void reconnect() {
// Loop until we're reconnected
status = WiFi.status();
if ( status != WL_CONNECTED) {
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
}
GND5VSDASCLSQWRTCDS1307+