#ifdef ESP8266
 #include <ESP8266WiFi.h>
 #else
 #include <WiFi.h>
#endif

#include <DHTesp.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>


#define DHTpin 21 //ejemplo 2
DHTesp dht;
// const int led = 5;  //ejemplo 5
#define led 14

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

const char* mqtt_server = "ffd0ab74da3e4815981d1f41c0d2a654.s2.eu.hivemq.cloud";
const char* mqtt_username = "marcos";
const char* mqtt_password = "75xN26@#";
const int mqtt_port = 8883;


WiFiClientSecure espClient; 
PubSubClient client(espClient);

unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];

static char strTemperature[10] = {0};
static char strHumidity[10] = {0};
/* Prototypes */
float getTemperature(void);
float getHumidity(void);

float getTemperature(void) {
  TempAndHumidity data = dht.getTempAndHumidity();
  Serial.println(".....");
  Serial.println(data.temperature);
  if ((isnan(data.temperature)))
    // return data.temperature;
    return ( std::rand() % ( 100) );
  else
    return -99.99;
}


float getHumidity(void) {
  TempAndHumidity data = dht.getTempAndHumidity();

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


/* Inicializa e conecta-se na rede WI-FI desejada */
void initWiFi(void)
{
  delay(10);
  Serial.println("------Conexao WI-FI------");
  Serial.print("Conectando-se na rede: ");
  Serial.println(SSID);
  Serial.println("Aguarde");

  reconnectWiFi();
}

void reconnect(void){
  //loop until we're reconnected
  while(!client.connected()){
    Serial.println(("Attempting MQTT connection..."));
    String clientId = "ESP32Client"; //create ramdom client id
    clientId += String(random(0xffff),HEX);
    //Attemp to connect
    if(client.connect(clientId.c_str(),mqtt_username,mqtt_password)){
      Serial.println(("connected"));
      client.subscribe("led_state");
    }else{
      Serial.println("failed,rc=");
      Serial.println(client.state());
      Serial.println(" try again in 5 sec");
      delay(5000);
    }
  }
}


void callback(char* topic, byte* payload, unsigned int length){
  String incommingMessage = "";
  for(int i=0;i<length;i++) incommingMessage+=(char)payload[i];

  Serial.println("message arrived ["+String(topic)+"]"+incommingMessage);

  // check incomming message
  if(strcmp(topic,"led_state")==0){
    if(incommingMessage.equals("1")) {
      digitalWrite(led, HIGH);
      Serial.println("ENCENDIDO");
    }else {
      digitalWrite(led, LOW);
      Serial.println("APAGADO");
    }
  }
}


void publishMessage(const char* topic,String payload, boolean retained){
  if(client.publish(topic,payload.c_str(),true))
    Serial.println("Mesaage publish ["+String(topic)+"]: "+payload);
}


void reconnectWiFi(void)
{
  // se já está conectado a rede WI-FI, nada é feito.
  // Caso contrário, são efetuadas tentativas de conexão
  if (WiFi.status() == WL_CONNECTED)
    return;

  WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI

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

  Serial.println();
  Serial.print("Conectado com sucesso na rede ");
  Serial.print(SSID);
  Serial.println("IP obtido: ");
  Serial.println(WiFi.localIP());
}


void setup() {
 
  // dht.setup(DHTpin,DHTesp::DHT11); //set up DHT11 sensor
  // pinMode(led, OUTPUT);
  Serial.begin(9600);
  // Configura o pino do LED como output e inicializa em nível baixo
  pinMode(led, OUTPUT);
  digitalWrite(led, HIGH);

  
  while(!Serial) delay(1);
   initWiFi(); //setup_wifi();

  // #ifdef ESP8266
    espClient.setInsecure();
  // #else
    // espClient.setCACert(root_ca); 
  // #endif
  client.setServer(mqtt_server, mqtt_port);
  Serial.println(client.connected());
  client.setCallback(callback);  
}

void loop() {
  
  if(!client.connected()) reconnect();
  client.loop();

  //read DHT11 temp & humi
  delay(dht.getMinimumSamplingPeriod());
  // float humidity = dht.getHumidity();
  // float temperature = dht.getTemperature();
  
  sprintf(strTemperature, "%.2fC", getTemperature());
  sprintf(strHumidity, "%.2f", getHumidity());

  DynamicJsonDocument doc(1024);

  doc["deviceId"] = "NodeMCU";
  doc["siteId"] = "My Demo Lab";
  doc["humidity"] = strHumidity; //humidity;
  doc["temperature"] = strTemperature; //temperature;

  char mqtt_message[128];
  serializeJson(doc,mqtt_message);

  publishMessage("esp8266-data",mqtt_message,true);

  delay(5000);


}
esp:VIN
esp:GND.2
esp:D13
esp:D12
esp:D14
esp:D27
esp:D26
esp:D25
esp:D33
esp:D32
esp:D35
esp:D34
esp:VN
esp:VP
esp:EN
esp:3V3
esp:GND.1
esp:D15
esp:D2
esp:D4
esp:RX2
esp:TX2
esp:D5
esp:D18
esp:D19
esp:D21
esp:RX0
esp:TX0
esp:D22
esp:D23
dht1:VCC
dht1:SDA
dht1:NC
dht1:GND
led1:A
led1:C
r1:1
r1:2
NOCOMNCVCCGNDINLED1PWRRelay Module
relay1:VCC
relay1:GND
relay1:IN
relay1:NC
relay1:COM
relay1:NO