#include "MQTTHandler.h" #include "WiFiConfig.h" extern Preferences preferences; // 引用外部定义的 preferences 对象 WiFiClient espClient; PubSubClient client(espClient); const char* mqttUser = "yangfei"; const char* mqttPassword = "yangfei"; static int lastGpio18State = LOW; // 保存上一次 GPIO18 的电平状态,默认为 LOW int mqttConnectionAttempts = 0; // 用于记录 MQTT 连接失败的次数 String targetDeviceID = ""; // 存储从订阅消息中接收的完整数据 // unsigned long lowGpioStartTime = 0; // 记录 GPIO18 低电平的开始时间 bool gpio18HighSent = false; // 标记是否已经发送过 ON 消息 void mqttSetup() { client.setServer(serverAddress.c_str(), serverPort); client.setCallback(mqttCallback); // 初始化 Preferences preferences.begin("mqtt", false); targetDeviceID = preferences.getString("targetDeviceID", ""); // 从存储中加载 targetDeviceID if (targetDeviceID.length() > 0) { Serial.println("[信息] 从存储中加载 targetDeviceID: " + targetDeviceID); } else { Serial.println("[信息] 未找到存储的 targetDeviceID"); } preferences.end(); } void mqttCallback(char* topic, byte* payload, unsigned int length) { String message = ""; for (unsigned int i = 0; i < length; i++) { message += (char)payload[i]; } String expectedTopic = "device/24G-" + deviceID + "/control"; // 订阅的主题 if (String(topic) == expectedTopic) { Serial.println("[信息] 收到控制消息: " + message); // 添加闪烁任务:发送第三个 MQTT 消息时闪烁 5 次 addBlinkTask(6); // 将接收到的完整消息存储到 targetDeviceID targetDeviceID = message; Serial.println("[信息] 存储 targetDeviceID: " + targetDeviceID); // 将 targetDeviceID 永久存储 preferences.begin("mqtt", false); preferences.putString("targetDeviceID", targetDeviceID); preferences.end(); Serial.println("[信息] 已永久存储 targetDeviceID: " + targetDeviceID); } } bool connectMQTT() { Serial.println("[信息] 尝试连接到 MQTT 服务器..."); if (client.connect(("24G-" + deviceID).c_str(), mqttUser, mqttPassword)) { Serial.println("[信息] MQTT 连接成功"); mqttConnectionAttempts = 0; // 连接成功时重置计数器 String topic = "device/24G-" + deviceID + "/control"; // 订阅的主题 client.subscribe(topic.c_str()); return true; } else { Serial.print("[错误] MQTT 连接失败, 错误码: "); Serial.println("服务器地址: " + serverAddress); Serial.println("服务器端口: " + String(serverPort)); Serial.println(client.state()); mqttConnectionAttempts++; // 连接失败时增加计数器 if (mqttConnectionAttempts >= 3) { Serial.println("[错误] MQTT 连接失败三次,进入 Wi-Fi 配置模式..."); setupWiFiConfig(); // 进入 Wi-Fi 配置模式 mqttConnectionAttempts = 0; // 重置计数器 } return false; } } void mqttLoop() { client.loop(); } // 实现发送 MQTT 消息的函数 void sendMQTTMessage(const char* message) { if (client.connected()) { String topic = "device/24G-" + deviceID + "/gpio18"; // 定义 MQTT 主题 client.publish(topic.c_str(), message); // 添加闪烁任务:发送第一个 MQTT 消息时闪烁 3 次 addBlinkTask(4); Serial.println("[信息] 发送 MQTT 消息: " + String(message)); } else { Serial.println("[错误] MQTT 未连接,无法发送消息"); } } // 新增函数:发送继电器控制消息 void sendRelayControlMessage(const char* state) { if (client.connected() && targetDeviceID.length() > 0) { // 组合发布主题:device//relay/control String topic = "device/" + targetDeviceID + "/relay/control"; String message = String(state); client.publish(topic.c_str(), message.c_str()); // 添加闪烁任务:发送第二个 MQTT 消息时闪烁 4 次 addBlinkTask(5); Serial.println("[信息] 发送继电器控制消息到设备 " + targetDeviceID + ": " + message); } else { Serial.println("[错误] MQTT 未连接或 targetDeviceID 未设置,无法发送继电器控制消息"); } } // 处理 GPIO18 状态并发送 high/low 消息 void handleGpio18State() { static int lastGpio18State = HIGH; // 保存上一次 GPIO18 的电平状态 int gpio18State = digitalRead(GPIO3_PIN); // 读取 GPIO18 的电平状态 // 如果电平状态发生变化 if (gpio18State != lastGpio18State) { if (gpio18State == HIGH) { sendMQTTMessage("high"); // 发送 high } else { sendMQTTMessage("low"); // 发送 low } lastGpio18State = gpio18State; // 更新上一次的电平状态 } } // 处理继电器控制逻辑,发送 ON/OFF 消息 void handleRelayControl() { static int lastGpio18State = HIGH; // 保存上一次 GPIO18 的电平状态 static unsigned long lowGpioStartTime = 0; // 记录低电平的开始时间 int gpio18State = digitalRead(GPIO3_PIN); // 读取 GPIO18 的电平状态 // 如果电平状态发生变化 if (gpio18State != lastGpio18State) { if (gpio18State == HIGH) { // GPIO18 从低电平变为高电平,立即发送 ON sendRelayControlMessage("ON"); Serial.println("发送:ON"); lowGpioStartTime = 0; // 重置低电平计时 } else if (gpio18State == LOW) { // GPIO18 从高电平变为低电平,开始计时 lowGpioStartTime = millis(); // 记录低电平开始时间 } lastGpio18State = gpio18State; // 更新上一次的电平状态 } // 如果当前是低电平且计时已经开始 if (gpio18State == LOW && lowGpioStartTime != 0) { if (millis() - lowGpioStartTime >= 15 * 60 * 1000) { // 15 分钟 // 低电平保持 15 分钟,发送 OFF sendRelayControlMessage("OFF"); Serial.println("发送:OFF"); lowGpioStartTime = 0; // 重置计时 } } }