#include <RTClib.h>
#include "my_lcd.h"
#include "my_wifi.h"
#include "PsychicMqttClient.h"
#include <DHT.h>
#define RED_LED_PIN 25
#define BLUE_LED_PIN 26
#define BUTTON_PIN 27
#define BUZZER_PIN 4
#define YELLOW_LED_PIN 14
MyLCD lcd;
RTC_DS1307 rtc;
MyWiFi wifi;
PsychicMqttClient mqttClient;
DHT dht(32, DHT22);
bool topicInited = false;
const char MQTTserver[] = "mqtt://mqtt-dashboard.com";
unsigned long lastPublish = 0;
unsigned long lastLCDUpdate = 0;
bool lastButtonState = HIGH;
bool alarmActive = false;
bool alarmStoppedByButton = false;
String lastLEDStatus = "";
bool mqttConnectedAnnounced = false;
unsigned long lastWateringTime = 0;
bool isWatering = false;
void mqttAlarmCtrl(const char *topic, const char *payload, int retain, int qos, bool dup) {
Serial.printf("Received control: %s\n", payload);
if (strcmp(payload, "stop") == 0) {
alarmStoppedByButton = true;
digitalWrite(RED_LED_PIN, LOW);
noTone(BUZZER_PIN);
alarmActive = false;
mqttClient.publish("productionplant/alarm", 1, 1, "Alarm stopped remotely");
} else if (strcmp(payload, "resume") == 0) {
alarmStoppedByButton = false;
mqttClient.publish("productionplant/alarm", 1, 1, "Alarm resumed remotely");
}
}
void mqttLED1(const char *topic, const char *payload, int retain, int qos, bool dup) {
Serial.printf("Received Topic: %s\r\n", topic);
Serial.printf("Received Payload: %s\r\n", payload);
}
void mqttLED2(const char *topic, const char *payload, int retain, int qos, bool dup) {
Serial.printf("Received Topic: %s\r\n", topic);
Serial.printf("Received Payload: %s\r\n", payload);
}
bool subscribe_topics() {
mqttClient.onTopic("productionplant/LED1", 1, mqttLED1);
mqttClient.onTopic("productionplant/LED2", 2, mqttLED2);
mqttClient.onTopic("productionplant/alarmctrl", 1, mqttAlarmCtrl);
return true;
}
void setup() {
Serial.begin(115200);
lcd.begin();
if (!rtc.begin()) {
lcd.print("RTC not found!");
while (1);
}
wifi.begin(&rtc);
dht.begin();
pinMode(RED_LED_PIN, OUTPUT);
pinMode(BLUE_LED_PIN, OUTPUT);
pinMode(YELLOW_LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(BLUE_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, LOW);
noTone(BUZZER_PIN);
lastWateringTime = millis() - 60000;
}
void loop() {
if (wifi.isTimeSynched()) {
if (!topicInited) {
mqttClient.setWill("productionplant/status", 1, true, "disconnected");
mqttClient.setServer(MQTTserver);
if (subscribe_topics()) topicInited = true;
}
if (!mqttClient.connected()) {
mqttClient.connect();
mqttConnectedAnnounced = false;
}
if (mqttClient.connected() && !mqttConnectedAnnounced) {
mqttClient.publish("productionplant/status", 1, 1, "connected");
mqttConnectedAnnounced = true;
}
}
float temp = dht.readTemperature();
float hum = dht.readHumidity();
unsigned long now = millis();
bool currentButtonState = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && currentButtonState == LOW) {
alarmStoppedByButton = !alarmStoppedByButton;
if (alarmStoppedByButton) {
digitalWrite(RED_LED_PIN, LOW);
noTone(BUZZER_PIN);
alarmActive = false;
mqttClient.publish("productionplant/alarm", 1, 1, "Alarm stopped by button");
} else {
mqttClient.publish("productionplant/alarm", 1, 1, "Alarm re-enabled");
}
}
lastButtonState = currentButtonState;
// ---------- 修改点:阈值与洒水位置 ----------
// 当湿度 <= 40% 时:红灯亮、响警报、洒水(保留按键停止逻辑)
// 当湿度 > 40% 时:绿灯亮(用 BLUE_LED_PIN 表示)、不洒水、不响警报
if (hum <= 40.0) {
if (!alarmStoppedByButton) {
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(BLUE_LED_PIN, LOW);
tone(BUZZER_PIN, 1000);
alarmActive = true;
lastLEDStatus = "RED_ON";
// 将洒水逻辑放在这里(湿度 <= 40 时洒水)
unsigned long elapsed = now - lastWateringTime;
if (!isWatering && elapsed >= 20000) {
isWatering = true;
lastWateringTime = now;
digitalWrite(YELLOW_LED_PIN, HIGH);
Serial.println("🚿 Start watering (YELLOW ON)");
}
if (isWatering && (now - lastWateringTime >= 10000)) {
isWatering = false;
digitalWrite(YELLOW_LED_PIN, LOW);
Serial.println("🛑 Stop watering (YELLOW OFF)");
}
} else {
// 用户按键停止警报/洒水时的行为(保持原有逻辑)
digitalWrite(RED_LED_PIN, LOW);
noTone(BUZZER_PIN);
alarmActive = false;
lastLEDStatus = "OFF";
isWatering = false;
digitalWrite(YELLOW_LED_PIN, LOW);
}
} else { // hum > 40.0
alarmStoppedByButton = false;
digitalWrite(RED_LED_PIN, LOW);
// 绿灯亮(使用 BLUE_LED_PIN 作为绿灯)
digitalWrite(BLUE_LED_PIN, HIGH);
noTone(BUZZER_PIN);
alarmActive = false;
lastLEDStatus = "GREEN_ON";
// 不洒水
isWatering = false;
digitalWrite(YELLOW_LED_PIN, LOW);
}
// ------------------------------------------
if (now - lastPublish > 2000) {
mqttClient.publish("productionplant/Temp", 2, 1, String(temp).c_str());
mqttClient.publish("productionplant/Curr", 1, 1, String(hum).c_str());
mqttClient.publish("productionplant/LEDStatus", 1, 1, lastLEDStatus.c_str());
mqttClient.publish("productionplant/Watering", 1, 1, isWatering ? "ON" : "OFF");
// ✅ 向手机 IoT MQTT Panel 汇报黄灯(洒水)状态
mqttClient.publish("/greenhouse/alarm", 1, 1, isWatering ? "on" : "off");
lastPublish = now;
}
if (now - lastLCDUpdate > 2000) {
lcd.display("ESP32-DevKitC-v4", "Humidity:", String(hum).c_str());
DateTime nowtime = rtc.now();
char dtbuf[21] = "YYYY-MM-DD hh:mm:ss";
nowtime.toString(dtbuf);
lcd.datetime(dtbuf);
lcd.alarm(1, "Temp UL1:", String(temp).c_str(), 0);
lcd.alarm(2, "Humid UL2:", String(hum).c_str(), "%");
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.setCursor(0, 3);
if (alarmStoppedByButton) {
lcd.print("Alarm Stopped");
} else if (alarmActive) {
lcd.print("!!! ALARM ON !!!");
} else {
lcd.print("Alarm cleared");
}
lcd.setCursor(10, 3);
if (isWatering) {
lcd.print("WATERING");
} else {
lcd.print(" ");
}
lastLCDUpdate = now;
}
}LCD (20x4) (I2C)
DS1307 RTC