#include <WiFi.h>
#include <PubSubClient.h>
#include <DHTesp.h>
#include <ArduinoJson.h>
#include <IRremote.h>
// Configurações de pinos
const int DHT_PIN = 15;
const int TRIGGER_PIN = 5;
const int ECHO_PIN = 18;
const int BUZZER_PIN = 19;
const int IR_LED_PIN = 4;
DHTesp dht;
// Configurações Wi-Fi e MQTT
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "test.mosquitto.org";
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
const long interval = 5000;
// Códigos IR (32 bits) - Controle Ar-Condicionado
const uint32_t CMD_DESLIGAR = 0x5E7E4778;
const uint32_t CMD_LIGAR = 0x5B657518;
const uint32_t TEMP_18 = 0x7BF13950;
const uint32_t TEMP_19 = 0x5B657518;
const uint32_t TEMP_20 = 0x456A9290;
const uint32_t TEMP_21 = 0x98F3E988;
const uint32_t TEMP_22 = 0xAEEECC10;
const uint32_t TEMP_23 = 0xD962CD58;
const uint32_t TEMP_24 = 0x1CD35750;
const uint32_t TEMP_25 = 0xAF9B1798;
const uint32_t FAN_V1 = 0x95356358;
const uint32_t FAN_V2 = 0xD6697710;
const uint32_t FAN_V3 = 0x65E47550;
bool runningSequence = false;
int temperaturaDesejada = -1; // -1 indica que não foi definida
int velocidadeVentilador = -1; // -1 indica que não foi definida
void sendNEC32(uint32_t code) {
IrSender.sendNEC(code, 32);
Serial.printf("Enviado IR: 0x%08X\n", code);
}
void startSequence() {
if (runningSequence) return;
runningSequence = true;
Serial.println(">>> Iniciando sequência automática...");
sendNEC32(CMD_LIGAR);
delay(300);
for (int t = 18; t <= 25 && runningSequence; t++) {
uint32_t code = 0;
switch (t) {
case 18: code = TEMP_18; break;
case 19: code = TEMP_19; break;
case 20: code = TEMP_20; break;
case 21: code = TEMP_21; break;
case 22: code = TEMP_22; break;
case 23: code = TEMP_23; break;
case 24: code = TEMP_24; break;
case 25: code = TEMP_25; break;
}
Serial.printf("Setando %d°C...\n", t);
sendNEC32(code);
temperaturaDesejada = t; // Atualiza a temperatura desejada
if (t == 23) {
Serial.println("Testando velocidades do ventilador...");
delay(1000);
sendNEC32(FAN_V1);
delay(1500);
sendNEC32(FAN_V2);
delay(1500);
sendNEC32(FAN_V3);
delay(1500);
velocidadeVentilador = 3; // Define ventilador na velocidade máxima
Serial.println("Velocidades testadas.");
}
delay(5000);
}
Serial.println(">>> Finalizando: 23°C com ventilador máximo (v3)");
sendNEC32(TEMP_23);
temperaturaDesejada = 23;
delay(500);
sendNEC32(FAN_V3);
velocidadeVentilador = 3;
runningSequence = false;
Serial.println(">>> Sequência concluída.");
}
void stopSequenceAndSendOff() {
runningSequence = false;
delay(200);
Serial.println(">>> Enviando comando DESLIGAR...");
sendNEC32(CMD_DESLIGAR);
temperaturaDesejada = -1; // Reseta a temperatura desejada
velocidadeVentilador = -1; // Reseta a velocidade do ventilador
}
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Conectando-se a ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi conectada");
Serial.println("Endereco IP: ");
Serial.println(WiFi.localIP());
}
// Função auxiliar para publicar mensagens MQTT
void publishStatus(const char* message) {
client.publish("/senai/status", message);
Serial.printf("Status publicado: %s\n", message);
}
void processMQTTCommand(String command) {
command.trim();
command.toLowerCase();
Serial.printf("Processando comando MQTT: %s\n", command.c_str());
char statusMsg[100]; // Buffer para mensagens de status
if (command == "ligar") {
startSequence();
publishStatus("Sequencia iniciada");
}
else if (command == "desligar") {
stopSequenceAndSendOff();
publishStatus("Ar condicionado desligado");
}
else if (command.startsWith("temp ")) {
int t = command.substring(5).toInt();
uint32_t code = 0;
switch (t) {
case 18: code = TEMP_18; break;
case 19: code = TEMP_19; break;
case 20: code = TEMP_20; break;
case 21: code = TEMP_21; break;
case 22: code = TEMP_22; break;
case 23: code = TEMP_23; break;
case 24: code = TEMP_24; break;
case 25: code = TEMP_25; break;
}
if (code) {
sendNEC32(code);
temperaturaDesejada = t; // Atualiza a temperatura desejada
snprintf(statusMsg, sizeof(statusMsg), "Temperatura definida: %d°C", t);
publishStatus(statusMsg);
} else {
Serial.println("Temperatura inválida (18–25).");
publishStatus("Erro: Temperatura invalida (18-25)");
}
}
else if (command.startsWith("fan ")) {
int v = command.substring(4).toInt();
if (v == 1) {
sendNEC32(FAN_V1);
velocidadeVentilador = v;
snprintf(statusMsg, sizeof(statusMsg), "Ventilador: Velocidade %d", v);
publishStatus(statusMsg);
}
else if (v == 2) {
sendNEC32(FAN_V2);
velocidadeVentilador = v;
snprintf(statusMsg, sizeof(statusMsg), "Ventilador: Velocidade %d", v);
publishStatus(statusMsg);
}
else if (v == 3) {
sendNEC32(FAN_V3);
velocidadeVentilador = v;
snprintf(statusMsg, sizeof(statusMsg), "Ventilador: Velocidade %d", v);
publishStatus(statusMsg);
}
else {
Serial.println("Velocidade inválida (1–3).");
publishStatus("Erro: Velocidade invalida (1-3)");
}
}
else if (command.startsWith("send ")) {
String hexStr = command.substring(5);
if (hexStr.startsWith("0x")) hexStr = hexStr.substring(2);
uint32_t val = strtoul(hexStr.c_str(), NULL, 16);
sendNEC32(val);
snprintf(statusMsg, sizeof(statusMsg), "Comando IR enviado: %s", hexStr.c_str());
publishStatus(statusMsg);
}
// Comandos diretos pelos nomes dos códigos
else if (command == "temp_18") {
sendNEC32(TEMP_18);
temperaturaDesejada = 18;
publishStatus("Temperatura: 18°C");
}
else if (command == "temp_19") {
sendNEC32(TEMP_19);
temperaturaDesejada = 19;
publishStatus("Temperatura: 19°C");
}
else if (command == "temp_20") {
sendNEC32(TEMP_20);
temperaturaDesejada = 20;
publishStatus("Temperatura: 20°C");
}
else if (command == "temp_21") {
sendNEC32(TEMP_21);
temperaturaDesejada = 21;
publishStatus("Temperatura: 21°C");
}
else if (command == "temp_22") {
sendNEC32(TEMP_22);
temperaturaDesejada = 22;
publishStatus("Temperatura: 22°C");
}
else if (command == "temp_23") {
sendNEC32(TEMP_23);
temperaturaDesejada = 23;
publishStatus("Temperatura: 23°C");
}
else if (command == "temp_24") {
sendNEC32(TEMP_24);
temperaturaDesejada = 24;
publishStatus("Temperatura: 24°C");
}
else if (command == "temp_25") {
sendNEC32(TEMP_25);
temperaturaDesejada = 25;
publishStatus("Temperatura: 25°C");
}
else if (command == "fan_1") {
sendNEC32(FAN_V1);
velocidadeVentilador = 1;
publishStatus("Ventilador: Velocidade 1");
}
else if (command == "fan_2") {
sendNEC32(FAN_V2);
velocidadeVentilador = 2;
publishStatus("Ventilador: Velocidade 2");
}
else if (command == "fan_3") {
sendNEC32(FAN_V3);
velocidadeVentilador = 3;
publishStatus("Ventilador: Velocidade 3");
}
else {
Serial.println("Comando não reconhecido.");
snprintf(statusMsg, sizeof(statusMsg), "Erro: Comando nao reconhecido: %s", command.c_str());
publishStatus(statusMsg);
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Mensagem recebida [");
Serial.print(topic);
Serial.print("] ");
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println(message);
// Processa comandos do tópico de controle do ar-condicionado
if (String(topic) == "/senai/ac/control") {
processMQTTCommand(message);
}
// Também processa comandos no tópico Subscribe antigo
else if (String(topic) == "/senai/Subscribe") {
Serial.println("Comando recebido no tópico Subscribe:");
processMQTTCommand(message);
}
}
void reconnect() {
while (!client.connected()) {
Serial.print("Tentando conexao MQTT...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("Conectado");
// Inscreve nos tópicos
client.subscribe("/senai/ac/control");
client.subscribe("/senai/Subscribe");
Serial.println("Inscrito nos tópicos:");
Serial.println(" /senai/ac/control");
Serial.println(" /senai/Subscribe");
publishStatus("Sistema iniciado - Pronto para comandos");
} else {
Serial.print("falhou, rc=");
Serial.print(client.state());
Serial.println(" tentando novamente em 5 segundos");
delay(5000);
}
}
}
void setup() {
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
Serial.begin(115200);
// Inicializa IR
Serial.println("\n=== Sistema Integrado Sensor + Controle IR ===");
IrSender.begin(IR_LED_PIN, ENABLE_LED_FEEDBACK);
Serial.printf("IR LED no pino %d\n", IR_LED_PIN);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
dht.setup(DHT_PIN, DHTesp::DHT22);
// Configurações do cliente MQTT
client.setBufferSize(1024); // Aumenta o buffer se necessário
client.setKeepAlive(60);
Serial.println("Sistema pronto - Aguardando comandos MQTT...");
Serial.println("Comandos disponíveis via MQTT:");
Serial.println(" ligar, desligar, temp XX, fan N, send 0xHEX");
Serial.println(" temp_18, temp_19, ..., temp_25, fan_1, fan_2, fan_3");
Serial.println("Tópicos inscritos:");
Serial.println(" /senai/ac/control");
Serial.println(" /senai/Subscribe");
}
void loop() {
if (!client.connected()) {
reconnect();
}
// Chama client.loop() com mais frequência
client.loop();
unsigned long now = millis();
if (now - lastMsg > interval) {
lastMsg = now;
// Leitura da temperatura e umidade
TempAndHumidity data = dht.getTempAndHumidity();
if (!isnan(data.temperature) && !isnan(data.humidity)) {
float temp = data.temperature;
float hum = data.humidity;
// Medição da distância usando o sensor ultrassônico
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
float distance = (duration * 0.034) / 2;
// Validação dos valores
if (distance > 400 || distance < 2) distance = -1;
// Cria o objeto JSON com todas as informações
StaticJsonDocument<400> doc; // Aumentado para 400 bytes
doc["temperatura_atual"] = temp;
doc["umidade"] = hum;
doc["distancia"] = distance;
doc["timestamp"] = millis();
doc["status"] = "OK";
// Adiciona informações do ar-condicionado
doc["temperatura_desejada"] = temperaturaDesejada;
doc["ventilador_velocidade"] = velocidadeVentilador;
doc["ar_condicionado_ligado"] = (temperaturaDesejada != -1);
// Serializa o JSON para um buffer
char jsonBuffer[512];
serializeJson(doc, jsonBuffer);
// Publica o JSON no tópico MQTT
client.publish("/senai/sensorData", jsonBuffer);
Serial.print("Dados enviados: ");
Serial.println(jsonBuffer);
// Controle do buzzer com base em limiares
bool alerta_distancia = (distance < 20.0 && distance > 0);
bool alerta_temperatura = (temp > 30.0);
bool alerta_umidade = (hum > 70.0);
if (alerta_distancia || alerta_temperatura || alerta_umidade) {
tone(BUZZER_PIN, 262, 250);
delay(300);
} else {
noTone(BUZZER_PIN);
}
} else {
Serial.println("Erro na leitura do DHT");
publishStatus("Erro: Falha na leitura do sensor DHT");
}
}
// Pequeno delay para não sobrecarregar
delay(10);
}