//Autor: Fábio Henrique Cabrini
//Adaptado CP5: Vinheria Agnello — ESP32 + DHT-22 + LDR + Buzzer
//Resumo: Publica temperatura, umidade e luminosidade no FIWARE via MQTT UltraLight.
// Recebe comando remoto para acionar LED azul (alerta) e buzzer.
//Pinagem (diagram.json Cabrini):
// DHT-22 → D4 (D35 é input-only, não funciona com DHT)
// LDR → D34 (AO)
// Buzzer → D32
// LED → D2 (onboard)
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
// ─── Configurações — variáveis editáveis ─────────────────────
const char* default_SSID = "Wokwi-GUEST"; // Nome da rede Wi-Fi
const char* default_PASSWORD = ""; // Senha da rede Wi-Fi
const char* default_BROKER_MQTT = "34.56.198.236"; // IP do Broker MQTT
const int default_BROKER_PORT = 1883; // Porta do Broker MQTT
const char* default_TOPICO_SUBSCRIBE = "/TEF/lamp001/cmd"; // Tópico MQTT de escuta
const char* default_TOPICO_PUBLISH_1 = "/TEF/lamp001/attrs"; // Tópico MQTT de envio de informações para Broker
const char* default_TOPICO_PUBLISH_2 = "/TEF/lamp001/attrs/l";// Tópico MQTT de luminosidade
const char* default_ID_MQTT = "fiware_001"; // ID MQTT
const int default_D4 = 2; // Pino do LED onboard
const char* topicPrefix = "lamp001"; // Prefixo do tópico
// Variáveis para configurações editáveis
char* SSID = const_cast<char*>(default_SSID);
char* PASSWORD = const_cast<char*>(default_PASSWORD);
char* BROKER_MQTT = const_cast<char*>(default_BROKER_MQTT);
int BROKER_PORT = default_BROKER_PORT;
char* TOPICO_SUBSCRIBE= const_cast<char*>(default_TOPICO_SUBSCRIBE);
char* TOPICO_PUBLISH_1= const_cast<char*>(default_TOPICO_PUBLISH_1);
char* TOPICO_PUBLISH_2= const_cast<char*>(default_TOPICO_PUBLISH_2);
char* ID_MQTT = const_cast<char*>(default_ID_MQTT);
int D4 = default_D4;
// ─── Pinos dos sensores ──────────────────────────────────────
#define DHT_PIN 4 // D4 — bidirecional, funciona com DHT22
#define DHT_TYPE DHT22
#define LDR_PIN 34 // AO do LDR (input only — só leitura, OK)
#define BUZZER_PIN 32 // Buzzer via resistor 1kΩ
// ─── Limiares de alerta para vinheria ────────────────────────
const float TEMP_MIN = 10.0; // °C
const float TEMP_MAX = 15.0; // °C
const float HUMID_MIN = 50.0; // %
const float HUMID_MAX = 70.0; // %
const int LUX_MAX = 300; // valor ADC (0–4095)
// ─── Intervalo de publicação ─────────────────────────────────
const unsigned long PUBLISH_INTERVAL = 5000; // ms
// ─── Objetos globais ─────────────────────────────────────────
DHT dht(DHT_PIN, DHT_TYPE);
WiFiClient espClient;
PubSubClient MQTT(espClient);
char EstadoSaida = '0'; // estado do LED ('0'=off, '1'=on)
bool ledRemoteOn = false; // LED acionado por comando remoto
bool ledBlink = false; // estado atual do pisca-pisca
unsigned long lastPublish = 0;
unsigned long lastBlink = 0;
// ============================================================
// Inicializações
// ============================================================
void initSerial() {
Serial.begin(115200);
}
void initWiFi() {
delay(10);
Serial.println("------Conexao WI-FI------");
Serial.print("Conectando-se na rede: ");
Serial.println(SSID);
Serial.println("Aguarde");
reconectWiFi();
}
void initMQTT() {
MQTT.setServer(BROKER_MQTT, BROKER_PORT);
MQTT.setCallback(mqtt_callback);
}
void InitOutput() {
pinMode(D4, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(D4, HIGH);
// Pisca LED na inicialização (igual ao código original)
boolean toggle = false;
for (int i = 0; i <= 10; i++) {
toggle = !toggle;
digitalWrite(D4, toggle);
delay(200);
}
digitalWrite(D4, LOW);
}
// ============================================================
// Setup
// ============================================================
void setup() {
InitOutput();
initSerial();
dht.begin();
initWiFi();
initMQTT();
delay(5000);
MQTT.publish(TOPICO_PUBLISH_1, "s|on");
}
// ============================================================
// Loop
// ============================================================
void loop() {
VerificaConexoesWiFIEMQTT();
EnviaEstadoOutputMQTT();
handleSensors();
MQTT.loop();
}
// ============================================================
// Reconexões
// ============================================================
void reconectWiFi() {
if (WiFi.status() == WL_CONNECTED) return;
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println();
Serial.println("Conectado com sucesso na rede ");
Serial.print(SSID);
Serial.println("IP obtido: ");
Serial.println(WiFi.localIP());
digitalWrite(D4, LOW);
}
void reconnectMQTT() {
while (!MQTT.connected()) {
Serial.print("* Tentando se conectar ao Broker MQTT: ");
Serial.println(BROKER_MQTT);
if (MQTT.connect(ID_MQTT)) {
Serial.println("Conectado com sucesso ao broker MQTT!");
MQTT.subscribe(TOPICO_SUBSCRIBE);
} else {
Serial.println("Falha ao reconectar no broker.");
Serial.println("Haverá nova tentativa de conexão em 2s");
delay(2000);
}
}
}
void VerificaConexoesWiFIEMQTT() {
if (!MQTT.connected()) reconnectMQTT();
reconectWiFi();
}
// ============================================================
// Callback — recebe comandos do FIWARE
// Mantém padrão original (lamp001@on|) e adiciona (lamp001@led|on)
// ============================================================
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
String msg = "";
for (int i = 0; i < length; i++) msg += (char)payload[i];
Serial.print("- Mensagem recebida: ");
Serial.println(msg);
// Padrão original do Cabrini
String onTopic = String(topicPrefix) + "@on|";
String offTopic = String(topicPrefix) + "@off|";
if (msg.equals(onTopic)) {
digitalWrite(D4, HIGH);
EstadoSaida = '1';
ledRemoteOn = true;
}
if (msg.equals(offTopic)) {
digitalWrite(D4, LOW);
EstadoSaida = '0';
ledRemoteOn = false;
noTone(BUZZER_PIN);
}
// Comando led (compatível com coleção CP5 futura)
if (msg.indexOf("@led|on") >= 0) {
ledRemoteOn = true;
EstadoSaida = '1';
Serial.println("→ LED ligado remotamente");
}
if (msg.indexOf("@led|off") >= 0) {
ledRemoteOn = false;
EstadoSaida = '0';
digitalWrite(D4, LOW);
noTone(BUZZER_PIN);
Serial.println("→ LED desligado remotamente");
}
}
// ============================================================
// Envia estado do LED (igual ao original)
// ============================================================
void EnviaEstadoOutputMQTT() {
if (EstadoSaida == '1') {
MQTT.publish(TOPICO_PUBLISH_1, "s|on");
Serial.println("- Led Ligado");
}
if (EstadoSaida == '0') {
MQTT.publish(TOPICO_PUBLISH_1, "s|off");
Serial.println("- Led Desligado");
}
Serial.println("- Estado do LED onboard enviado ao broker!");
delay(1000);
}
// ============================================================
// Alertas sonoros — tom distinto por anomalia
// Temperatura : 3 bips curtos agudos (2000 Hz)
// Umidade : 2 bips longos graves (800 Hz)
// Luminosidade: bip rápido contínuo (3500 Hz)
// ============================================================
void alertTemperature() {
Serial.println("⚠ ALERTA: Temperatura fora da faixa!");
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, 2000, 150);
delay(300);
}
}
void alertHumidity() {
Serial.println("⚠ ALERTA: Umidade fora da faixa!");
for (int i = 0; i < 2; i++) {
tone(BUZZER_PIN, 800, 500);
delay(700);
}
}
void alertLuminosity() {
Serial.println("⚠ ALERTA: Luminosidade alta!");
tone(BUZZER_PIN, 3500, 100);
delay(200);
}
// ============================================================
// Pisca LED via millis() — não trava o loop MQTT
// ============================================================
void handleLedBlink() {
unsigned long now = millis();
if (ledRemoteOn && (now - lastBlink >= 300)) {
lastBlink = now;
ledBlink = !ledBlink;
digitalWrite(D4, ledBlink);
} else if (!ledRemoteOn) {
ledBlink = false;
}
}
// ============================================================
// Leitura e publicação dos sensores (substitui handleLuminosity)
// ============================================================
void handleSensors() {
handleLedBlink();
unsigned long now = millis();
if (now - lastPublish < PUBLISH_INTERVAL) return;
lastPublish = now;
// ── Leitura dos sensores ─────────────────────────────────
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
int sensorValue = analogRead(LDR_PIN);
int luminosity = map(sensorValue, 0, 4095, 0, 100); // 0–100% igual ao original
if (isnan(temperature) || isnan(humidity)) {
Serial.println("[ERRO] Falha na leitura do DHT-22!");
return;
}
// ── Verifica alertas ─────────────────────────────────────
bool tempAlert = (temperature < TEMP_MIN || temperature > TEMP_MAX);
bool humidAlert = (humidity < HUMID_MIN || humidity > HUMID_MAX);
bool luxAlert = (luminosity > LUX_MAX);
if (tempAlert) alertTemperature();
if (humidAlert) alertHumidity();
if (luxAlert) alertLuminosity();
// Pisca LED localmente se há alerta e LED remoto não está ativo
bool anyAlert = tempAlert || humidAlert || luxAlert;
if (anyAlert && !ledRemoteOn) {
digitalWrite(D4, !digitalRead(D4));
}
// ── Publica no formato UltraLight ─────────────────────────
// Tópico 1 (attrs): temperatura e umidade juntos
String payloadAttrs = "t|" + String(temperature, 1) +
"|h|" + String(humidity, 1);
MQTT.publish(TOPICO_PUBLISH_1, payloadAttrs.c_str());
// Tópico 2 (attrs/l): luminosidade separada (igual ao original)
String payloadLux = String(luminosity);
MQTT.publish(TOPICO_PUBLISH_2, payloadLux.c_str());
// ── Log Serial ───────────────────────────────────────────
Serial.println("════════════════════════════════");
Serial.print("Valor da luminosidade: "); Serial.println(payloadLux);
Serial.printf("Temp: %.1f°C | Umid: %.1f%% | Lux: %d%%\n",
temperature, humidity, luminosity);
if (anyAlert) Serial.println("⚠ ALERTA ATIVO!");
else Serial.println("✓ Valores normais");
}