| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- #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 = ""; // 存储从订阅消息中接收的完整数据
- 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/<targetDeviceID>/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 gpio18Voltage = analogRead(GPIO3_PIN); // 读取 GPIO18 的电压值
- int gpio18State = (gpio18Voltage > 2 * 1023 / 3.3) ? HIGH : LOW; // 判断高低电平
- // 如果电平状态发生变化
- 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 gpio18Voltage = analogRead(GPIO3_PIN); // 读取 GPIO18 的电压值
- int gpio18State = (gpio18Voltage > 2 * 1023 / 3.3) ? HIGH : LOW; // 判断高低电平
- // 如果电平状态发生变化
- 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; // 重置计时
- }
- }
- }
|