// Exmaple of using the MQTT library for ESP32 
// Library by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
// Modified by Arnan Sipitakiat


#include <WiFi.h>
#include <MQTT.h>

const int trigPin = 5;
const int echoPin = 18;
const int LED_PIN = 23;

//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701

long duration;
float distanceCm;
float distanceInch;

const char ssid[] = "Wokwi-GUEST";
const char pass[] = "";

const char mqtt_broker[]="broker.hivemq.com";
const char mqtt_topic[]="patipan";
const char mqtt_client_id[]="arduino_group_x"; // must change this string to a unique value
int MQTT_PORT=1883;

int counter=0;

WiFiClient net;
MQTTClient client;

unsigned long lastMillis = 0;

void connect() {
  Serial.print("checking wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }

  Serial.print("\nconnecting...");
  while (!client.connect(mqtt_client_id)) {  
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\nconnected!");

  client.subscribe(mqtt_topic);
  // client.unsubscribe("/hello");
}

void messageReceived(String &topic, String &payload) 
{ 
  Serial.println("incoming: " + topic + " - " + payload); //รับค่าจาก hive เขียนใน toppic
  if(payload==String('1')) digitalWrite(LED_PIN, HIGH);
  if(payload==String('0')) digitalWrite(LED_PIN, LOW);

  // Note: Do not use the client in the callback to publish, subscribe or
  // unsubscribe as it may cause deadlocks when other things arrive while
  // sending and receiving acknowledgments. Instead, change a global variable,
  // or push to a queue and handle it in the loop after calling `client.loop()`.
}

void setup() 
{
  Serial.begin(9600);
  WiFi.begin(ssid, pass);

  // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
  // by Arduino. You need to set the IP address directly.
  client.begin(mqtt_broker, MQTT_PORT, net);
  client.onMessage(messageReceived);

  connect();

  Serial.begin(115200); // Starts the serial communication
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  client.loop();
  delay(10);  // <- fixes some issues with WiFi stability

  if (!client.connected()) {
    connect();
  }

  // publish a message roughly every second.
  // not that we don't use delay() because we need to keep calling the client.loop()
  // to keep the connection alive
  /*
  if (millis() - lastMillis > 2000) {
    lastMillis = millis();
    client.publish("ESP102","LEDon");
    delay(2000);
  }
  */
  //ลูปวงจร
  // 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);

  //Calculate the distance
  distanceCm = duration * SOUND_SPEED/2;
  
  if(distanceCm < 100)
  {   
    digitalWrite(LED_PIN, HIGH);
    if (millis() - lastMillis > 2000) {
      lastMillis = millis();
      client.publish("ESP120","1");
      delay(2000);
    }
  }
  else
  {
    digitalWrite(LED_PIN, LOW);
    if (millis() - lastMillis > 2000) {
      lastMillis = millis();
      client.publish("ESP120","0");
      delay(2000);
    }
  }
    
  // Convert to inches
  distanceInch = distanceCm * CM_TO_INCH;

  // Prints the distance in the Serial Monitor
  Serial.print("Distance (cm): ");
  Serial.println(distanceCm);
  //Serial.print("Distance (inch): ");
  //Serial.println(distanceInch);
  delay(2000);
  //wifi
  //delay(2000);
}