#include "DHTesp.h"
#include "PubSubClient.h"
#include "WiFi.h"
#include "ESP32Servo.h"

const int DHT_PIN = 15;
const int LED_PIN = 13;
const int Servo_PIN = 12;
const int pir_PIN = 14;

const char* ssid = "Wokwi-GUEST";
const char* pass = "";
const char* broker = "broker.hivemq.com";
const char* subs_lamp = "Led1";
const char* subs_servo = "servo1";
const char* pub_temp = "tempiot";
const char* pub_humi = "humiiot";
const char* pub_pir = "pir1";
const int brokerPort = 1883;

String macAddr;
String ipAddr;
bool isMovement = false;

Servo myservo;
DHTesp dhtSensor;
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);

void WifiSetup(){
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  while(WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(500);
  }

  ipAddr = WiFi.localIP().toString().c_str();
  macAddr = WiFi.macAddress();

  Serial.print("Connected at: ");
  Serial.println(ipAddr);
  // Serial.println(WiFi.localIP());
  Serial.print("MAC: ");
  Serial.println(macAddr);
}
void MqttSetup(){

  mqtt.setServer(broker, brokerPort);
  mqtt.setCallback(Callback);
}

void Reconnect(){
  Serial.println("Connecting to MQTT Broker...");
  while (!mqtt.connected()) {
      Serial.println("Reconnecting to MQTT Broker..");
      String clientId = "ESP32Client-";
      clientId += String(random(0xffff), HEX);
      
      if (mqtt.connect(clientId.c_str())) {
        Serial.print("ID: ");
        Serial.println(clientId);
        Serial.println("Connected.");
        mqtt.subscribe(subs_lamp);
        mqtt.subscribe(subs_servo);
      }      
      else {
        Serial.print("failed, rc=");
        Serial.print(mqtt.state());
        Serial.println(" try again in 5 seconds");
        delay(5000);
      }
  }
}

// for mqtt-subscriber
void Callback(char* topic, byte* message, unsigned int length){

  Serial.print("Incoming topic: ");
  Serial.println(topic);
  
  String _messageStr;

  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    _messageStr += (char)message[i];
  }

  Serial.println();

  if(String(topic) == subs_lamp){
    _messageStr.toLowerCase();
    Serial.print("Output to: ");

    if( _messageStr == "1"){
      Serial.println("LED ON");
      digitalWrite(LED_PIN, HIGH);
    }
    else if( _messageStr == "0"){
      Serial.println("LED OFF");
      digitalWrite(LED_PIN, LOW);
    }
  }
  else if( String(topic) == subs_servo){

    int a = map(_messageStr.toInt(), 0, 100, 0, 180);
    myservo.write(a);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(Servo_PIN, OUTPUT);
  pinMode(pir_PIN, INPUT);

  WifiSetup();
  MqttSetup();

  myservo.attach(Servo_PIN);
  dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
}

// for mqtt-publisher
void loop() {

  if( !mqtt.connected()){
    Reconnect();
  }

  mqtt.loop();

  TempAndHumidity  data = dhtSensor.getTempAndHumidity();
  float t = data.temperature;
  float h = data.humidity;
  
  char _t[8];
  dtostrf(t, 1, 2, _t);
  mqtt.publish(pub_temp, _t);
  Serial.print("Pub Temp: ");
  Serial.println(_t);

  char _h[8];
  dtostrf(h, 1, 2, _h);
  mqtt.publish(pub_humi, _h);
  Serial.print("Pub Hum: ");
  Serial.println(_h);

  //tambah ini buat publish nya 
  char _p[2];
  _p[0] = '1';
  int pir = digitalRead(pir_PIN);
  
  if(pir==1 && isMovement == false){
   mqtt.publish(pub_pir, _p);
   isMovement = true;
   Serial.println("publish");
  }

  if( pir == 0){
    isMovement = false;
  }
  
  delay(1000);
}