#include <WiFi.h>
#include <PubSubClient.h>
// --- Configuración de la red Wi-Fi ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// --- Configuración del Broker MQTT ---
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883; // Puerto MQTT estándar (cambiado desde 8084)
const char* mqtt_user = "";
const char* mqtt_password = "";
// --- Configuracion de los Topicos
const char* alarmControlTopic = "alarma/control";
const char* alarmStatusTopic = "alarma/estatus";
const char* sensorTopic = "alarma/sensor";
// --- Pines ---
const int pirPin = 13;
const int redPin = 16; // Pin PWM para el LED Rojo
const int greenPin = 17; // Pin PWM para el LED Verde
const int bluePin = 18; // Pin PWM para el LED Azul
const int buzzerPin = 25;
// --- Estados de la Alarma ---
enum AlarmState {
CONNECTING,
INACTIVE,
ACTIVE,
ALARM
};
AlarmState currentState = CONNECTING;
bool alarmArmed = false;
// --- LED RGB (Control por PWM) ---
// #define NUM_LEDS 1
// CRGB leds[NUM_LEDS]; // Elimina la definición del array de LEDs FastLED
WiFiClient espClient;
PubSubClient client(espClient);
// --- Funciones Auxiliares ---
// Función para establecer el color RGB con PWM (0-255 para cada componente)
void setLedColor(uint8_t red, uint8_t green, uint8_t blue) {
// Para un LED de ánodo común conectado a VCC, LOW enciende, HIGH apaga
analogWrite(redPin, 255 - red);
analogWrite(greenPin, 255 - green);
analogWrite(bluePin, 255 - blue);
}
void playSiren() {
// Aquí iría la lógica para activar la corneta con sonido de sirena
// Esto dependerá del tipo de corneta y si necesitas generar tonos PWM
Serial.println("¡¡¡Sirena sonando!!!");
tone(buzzerPin, 1000); // Ejemplo de tono a 1000Hz
delay(200);
noTone(buzzerPin);
delay(100);
tone(buzzerPin, 1500);
delay(200);
noTone(buzzerPin);
delay(500);
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Mensaje recibido en [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if (strcmp(topic, alarmControlTopic) == 0) {
if (strncmp((char*)payload, "on", length) == 0) {
alarmArmed = true;
currentState = ACTIVE;
client.publish(alarmStatusTopic, "Alarma activada");
} else if (strncmp((char*)payload, "off", length) == 0) {
alarmArmed = false;
currentState = INACTIVE;
client.publish(alarmStatusTopic, "Alarma desactivada");
}
}
}
void reconnect() {
while (!client.connected()) {
Serial.print("Intentando conectar a MQTT...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
Serial.println("Conectado a MQTT");
client.subscribe(alarmControlTopic);
currentState = INACTIVE; // Al conectarse, está inactivo
client.publish(alarmStatusTopic, "Inactivo");
} else {
Serial.print("Error al conectar a MQTT, rc=");
Serial.println(client.state());
Serial.println("Reintentando en 5 segundos...");
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(pirPin, INPUT);
pinMode(buzzerPin, OUTPUT);
// FastLED.addLeds<WS2811, NUM_LEDS, GRB>(leds, 800000); // Elimina la inicialización de FastLED
// FastLED.setBrightness(50); // Elimina el ajuste de brillo de FastLED
pinMode(redPin, OUTPUT); // Configura los pines del LED RGB como salidas
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
// --- Conexión Wi-Fi ---
Serial.println("Conectando a Wi-Fi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
setLedColor(255, 165, 0); // Naranja: Conectando a Wi-Fi
delay(500);
}
Serial.println("Conectado a Wi-Fi");
setLedColor(0, 0, 255); // Azul: Wi-Fi conectado
// --- Conexión MQTT ---
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
reconnect();
}
void loop() {
if (!client.connected()) {
setLedColor(255, 0, 0); // Rojo parpadeante: Error de conexión MQTT
delay(200);
setLedColor(0, 0, 0);
delay(200);
reconnect();
delay(1000);
}
client.loop();
// --- Lógica del Sensor de Movimiento ---
int pirValue = digitalRead(pirPin);
if (alarmArmed && pirValue == HIGH) {
currentState = ALARM;
Serial.println("¡¡¡MOVIMIENTO DETECTADO!!! ¡¡¡ALARMA!!!");
client.publish(sensorTopic, "Sensor de Movimiento");
playSiren();
delay(5000); // Mantener la sirena y el estado de alarma por un tiempo
currentState = ACTIVE; // Volver al estado activo después
}
// --- Actualizar el LED RGB según el estado ---
switch (currentState) {
case CONNECTING:
// Ya se manejó en el setup
break;
case INACTIVE:
setLedColor(0, 255, 0); // Verde: Inactivo
break;
case ACTIVE:
setLedColor(255, 255, 0); // Amarillo: Activo
break;
case ALARM:
// Parpadeo rojo para la alarma usando PWM
for (int i = 0; i < 5; i++) {
setLedColor(255, 0, 0); // Rojo brillante
delay(200);
setLedColor(0, 0, 0); // Apagado
delay(200);
}
break;
}
delay(50); // Pequeño retardo en el loop
}