/*=================================================================================
CETEC CAPACITAÇÕES
Capacitação no aplicativo Wokwi.
Coordenador: Professor Luiz Tetsuharu Saito
Professor: Juliano Koichi Tanabe
SETEMBRO DE 2024
Aluno: Carlos Barreira da Silva Farinhas
ETEC Aristóteles Ferrreira - Santos
Projeto 1 – Montar um circuito ESP 32 conectado a um display OLED SSD1306 e um
sensor DHT22 no Wokwi.
A programação (na linguagem C/Arduino) deverá ler a temperatura e umidade
simuladas no DHT22, e exibir os valores medidos de temperatura e umidade no 
display OLED.
Os valores também deverão ser enviados pelo protocolo MQTT ao test.mosquitto.org,
porta 1883 como mensagem de tópico.
Um app deverá ser desenvolvido no App Inventor e deverá conectar-se e consultar
o tópico, no test.mosquitto.org, enviado pelo ESP32, quando este estiver em modo
de simulação no Wokwi, com os dados de temperatura e umidade e exibir as
informações em tela.
=================================================================================*/
//Bibliotecas utilizadas
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <Adafruit_SSD1306.h>
//constantes
#define DHTPIN 4
#define DHTTYPE DHT22
#define TOPIC "barPr1" //MUDAR O TÓPICO
//Dados do WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "test.mosquitto.org";
//Declarações e classes
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
// --- Declaração para o display SSD1306 connectado ao I2C (pinos SDA, SCL) ----
Adafruit_SSD1306 display(128, 64, & Wire, -1);
void setup() {
  //Inicialização do serial
    Serial.begin(115200);
    // Chamada das funções de configuração do WiFi, do MQTT e do sensor
    setup_wifi();
    client.setServer(mqtt_server, 1883);
    dht.begin();
  // --- inicialização do display OLED ---
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Endereço 0x3C para 128x64
  display.clearDisplay(); // garante que o display começa vazio
}
void loop() {
  reconnect();
  
  client.loop();
  // lendo o sensor e guardando dados na variáveis
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  // Caso o sensor não envie dados, será mostrada esta mensagem no monitor serial
  if (isnan(h) || isnan(t)) {
    Serial.println("Sem dados do sensor!");
    return;
  }
  Serial.println(h);
  Serial.println(t);
  //Dados que serão enviados ao servidor MQTT
  String payload = "{";
  payload += "\"Umidade  \":";
  payload +=  String(h);
  payload += ",\"Temperatura  \":";
  payload += String(t);
  payload += "}";
  //Envio de dados ao servidor MQTT e mensagem de sucesso ou não
  if (client.publish(TOPIC, (char*) payload.c_str(), true)) {
    Serial.println("Mensagem publicada com sucesso");
  } else {
    Serial.println("Falha na publicação da mensagem");
  }
// configuração do display 
display.setTextSize(1);
display.setTextColor(WHITE);	
// mostrar temperatura
display.setCursor(5,10);
display.print("Temperatura =  ");
display.setCursor(90,10);
display.print(t);
// mostrar umidade
display.setCursor(5,40);
display.print("Umidade =  ");
display.setCursor(90,40);
display.print(h);
// mandar para o display
display.display();
delay(2000);
// limpa o display
display.clearDisplay( );
}
//Funcão para configurar o WiFi
void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
//Função para reconectar ao servidor em caso de desconexão
void reconnect ( void ) {
  if ( ! client.connected ( ) ) {  
    
    while ( ! client.connected ( ) ) {     
      
      Serial.print ( F ( "Conectando novamente ao servidor" ) );
      if ( client.connect ( "Client_test" ) ) {  
        Serial.println ( F ( "Cliente conectado" ) );
      } else {    
        
        Serial.print ( F ( "Falha ao conectar, tipo de erro: " ) );
        Serial.print ( client.state ( ) );     // Tipo de erro de conexão
        Serial.println ( F ( "  Tentando novamente em 5 segundos" ) );
        delay ( 5000 );
      }
    }
  }
}