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

//pin Define
#define PIN_Relay 2 // GPIO to Relay

/* Configuration of Topic to MQTT */
#define TOPIC_SUBSCRIBE_Relay "Relay"
#define TOPIC_SUBSCRIBE_Siren "Siren"
#define PUBLISH_DELAY 2000

#define ID_MQTT "esp32_mqtt"

const char *SSID = "Wokwi-GUEST"; // SSID / nome da rede WI-FI que deseja se conectar
const char *PASSWORD = "";        // Senha da rede WI-FI que deseja se conectar

// URL for MQTT broker
const char *BROKER_MQTT = "broker.hivemq.com";
int BROKER_PORT = 1883; // Port of Broker MQTT

// Variable for Wifi Client Object
WiFiClient espClient;         
PubSubClient MQTT(espClient);

unsigned long publishUpdate;

void initWiFi(void);
void initMQTT(void);
void callbackMQTT(char *topic, byte *payload, unsigned int length);
void reconnectMQTT(void);
void reconnectWiFi(void);
void checkWiFIAndMQTT(void);

/* Function for get Temperature  
float getTemperature(void)
{
  TempAndHumidity data = dht.getTempAndHumidity();

  if (!(isnan(data.temperature)))
    return data.temperature;
  else
    return -99.99;
}
*/
/* Function for get Humidity  
float getHumidity(void)
{
  TempAndHumidity data = dht.getTempAndHumidity();

  if (!(isnan(data.humidity)))
    return data.humidity;
  else
    return -99.99;
}
*/

/* Initial WI-FI  */
void initWiFi(void)
{
  delay(10);
  Serial.println("------Connect to WI-FI------");
  Serial.print("Connecting to : ");
  Serial.println(SSID);

  reconnectWiFi();
}

/* Initial MQTT  */
void initMQTT(void)
{
  MQTT.setServer(BROKER_MQTT, BROKER_PORT); 
  MQTT.setCallback(callbackMQTT);
}

/* Function Callback: Receive Message from another MQTT Client publish message pass through the MQTT Broker */
void callbackMQTT(char *topic, byte *payload, unsigned int length)
{
  String msg;

  // Obtem a string do payload recebido
  for (int i = 0; i < length; i++) {
    char c = (char)payload[i];
    msg += c;
  }

  Serial.printf("Receive string via MQTT: %s on topico: %s\n", msg, topic);

  /* Toma ação dependendo da string recebida */
  if (msg == "1") {
    digitalWrite(PIN_Relay, HIGH);
    Serial.println("Siren ON");
  }

  if (msg == "0") {
    digitalWrite(PIN_Relay, LOW);
    Serial.println("Relay ON");
  }
  
}

/* FUnction reconnect MQTT Broker */
void reconnectMQTT(void)
{
  while (!MQTT.connected()) {
    Serial.print("* Connecting MQTT Broker: ");
    Serial.println(BROKER_MQTT);
    if (MQTT.connect(ID_MQTT)) {
      Serial.println("Connecting the MQTT Broker success!");
      MQTT.subscribe(TOPIC_SUBSCRIBE_Relay);
      MQTT.subscribe(TOPIC_SUBSCRIBE_Siren);
    } else {
      Serial.println("Fail to connect then reconnect MQTT Broker again in 2 seconds.");
      delay(2000);
    }
  }
}

/* Function checking connected to WiFI and MQTT Broker */
void checkWiFIAndMQTT(void)
{
  if (!MQTT.connected()){
    reconnectMQTT(); 
  }
  reconnectWiFi(); 
}

void reconnectWiFi(void)
{
  if (WiFi.status() == WL_CONNECTED)
    return;

  WiFi.begin(SSID, PASSWORD); 

  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("Connected WiFi success. ");
  Serial.print(SSID);
  Serial.println("IP Address: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  pinMode(PIN_Relay, OUTPUT);

  initWiFi();
  initMQTT();

}

void loop() {
  /* Repeat every 2 seconds (PUBLISH_DALAY)*/

  if ((millis() - publishUpdate) >= PUBLISH_DELAY) {
    publishUpdate = millis();
    // Verifica o funcionamento das conexões WiFi e ao broker MQTT
    checkWiFIAndMQTT();

    // Keep-alive for connected MQTT broker
    MQTT.loop();
  }

}
NOCOMNCVCCGNDINLED1PWRRelay Module