//Libraries
#include <WiFiManager.h> 
#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include <Wire.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include<ADS1115_WE.h> 
#define I2C_ADDRESS 0x48

// inisiasi sensor
#define DHTPIN D6           //pin DHT
#define DHTTYPE DHT21       //DHT 21  (AM2301)

// Sensor variable 
int MQTTLED = D3;
int WIFILED = D5;
const int SoilSensor = A0;

float voltage = 0.0; //batery level
float hum;  //Stores humidity value
float temp; //Stores temperature value
float lux;  //Stores light intensity value
float tanah;
int thresholdValue = 800;   // tresshold
DHT dht(DHTPIN, DHTTYPE);   //Initialize DHT sensor for normal 16mhz Arduino
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
ADS1115_WE adc = ADS1115_WE(I2C_ADDRESS);

// inisisasi mqtt broker
//MQTT config
bool useMQTT = true;
const char* mqttServer = "192.168.43.27";
const char* mqttUsername = ""; 
const char* mqttPassword = "";
char outTopic[] = "SHT1/sensor";

// const char* mqttServer = "103.240.110.132";
// const char* HostName = "localhost";
// const char* mqttUser = "arsenet";
// const char* mqttPassword = "P@ssw0rd@2023";
WiFiClient espClient;
PubSubClient client(espClient);
// char outTopic[] = "pnbp_d2/sensor";
char buffer[256];

      void reconnect() {
        while (!client.connected()) {
          Serial.print("Attempting MQTT connection...");
          if (client.connect(mqttServer, mqttUsername, mqttPassword)) {
            Serial.println("MQTT connected");
            digitalWrite(MQTTLED, LOW);
            } 
          else {
            digitalWrite(MQTTLED, HIGH);
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 3 seconds");   
            delay(2000);
            digitalWrite(MQTTLED, LOW);
            delay(1000);}
        }
      }

      float readChannel(ADS1115_MUX channel) {
        float voltage = 0.0;
        adc.setCompareChannels(channel);
        adc.startSingleMeasurement();
        while(adc.isBusy()){}
          voltage = adc.getResult_V(); // alternative: getResult_mV for Millivolt
          return voltage;
      }
 
// config sensor TSL2561
        void configureSensor(void){
          tsl.enableAutoRange(true);            /* Auto-gain ... switches automatically between 1x and 16x */
          tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */ 
          // Serial.println("------------------------------------");
          // Serial.print  ("Gain:         "); Serial.println("Auto");
          // Serial.print  ("Timing:       "); Serial.println("13 ms");
          // Serial.println("------------------------------------");
        }
// interval loop 
unsigned long interval=2000; // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.

void setup(){
  Serial.begin(115200);
  pinMode(MQTTLED, OUTPUT); 
  pinMode(WIFILED, OUTPUT);
  ///////////////////////
  // Setup wifi manager
  WiFiManager wm;
  //wm.resetSettings();
  bool res;
  res = wm.autoConnect("SKK_SOILDHTLUX","password"); // password protected ap
  if(!res) {
    Serial.println("Failed to connect");
    digitalWrite(WIFILED, HIGH);
    } 
  else {
    Serial.println("connected... :)");
    digitalWrite(WIFILED, LOW);
    }
  // Set MQTT Connection
  client.setServer(mqttServer, 1883);
  ////////////
  dht.begin();//DHT21
  Wire.begin();//I2C
  if(!adc.init()){
    Serial.println("ADS1115 not connected!");
    }
  adc.setVoltageRange_mV(ADS1115_RANGE_6144);
  // Setup sensors INTENSITAS
  configureSensor();
      if(!tsl.begin()){
          Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
          //while(1);
          }
          Serial.println("");  
  }

void readsensor() {
  voltage = readChannel(ADS1115_COMP_0_GND);
  tanah = analogRead(SoilSensor);
  hum = dht.readHumidity();
  temp= dht.readTemperature();
  ///////////
  sensors_event_t event;
  tsl.getEvent(&event);
  if (event.light) {
    lux = event.light; 
  } 
  else {
    Serial.println("Sensor overload");
  }
  //////////////
  Serial.print("Kelembapan tanah: "); Serial.println(tanah); 
  Serial.print("Kelembapan: "); Serial.println(hum); 
  Serial.print("Temperature: "); Serial.print(temp); Serial.println(" Celsius"); 
  Serial.print("Intensitas Cahaya: "); Serial.print(lux); Serial.println(" lux");
  Serial.print("Tegangan: ");  Serial.print(voltage);  Serial.println(" VDC ");

  // create json to data publish sensor
  StaticJsonDocument<200> doc;
  doc["soil"] = tanah;
  doc["humidity"] = hum;
  doc["temperature"] = temp;
  doc["intensity"] = lux;
  doc["batlevel"] = voltage;
  serializeJson(doc, buffer);
  client.publish("outTopic", buffer);  
}

void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= interval){
    readsensor();
    previousMillis = millis();
  }
}
