//安装ArduinoMqttClient库
//安装ArduinoJson库
//安装DHT11库  DHT sensor library

#include <WiFi.h>
#include <ArduinoMqttClient.h>
#include <DHT.h>
#include <ArduinoJson.h>

#define DHT_PIN 15
#define DHT_TYPE DHT11

DHT dht(DHT_PIN, DHT_TYPE);

// WiFi 配置
const char* ssid = "rehome";
const char* password = "Ruihong123";

// MQTT 配置
const char* mqtt_server = "47.242.184.139"; // hk服务器
const int mqtt_port = 1883;
const char* mqtt_user = "admin"; // 如果需要认证
const char* mqtt_password = "publish452131wW452131wW$";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char topic[] = "esp32/status";

unsigned long lastSensorRead = 0;
const long sensorInterval = 10000; // 10秒

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("正在连接: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi 连接成功");
  Serial.print("IP 地址: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!mqttClient.connected()) {
    Serial.println("尝试 MQTT 连接...");
    // 设置认证帐号和密码
    mqttClient.setUsernamePassword(mqtt_user, mqtt_password);
    // 客户端 ID
    mqttClient.setId("ArduinoMqttClient_dht11_" + String(random(0xffff), HEX));
    // 尝试连接
    if(mqttClient.connect(mqtt_server, mqtt_port)) {
      Serial.println("MQTT连接成功");
      // 订阅主题
      // Subscribe to topic
      //mqttClient.subscribe(topic);
      //Subscribe with QoS
      mqttClient.subscribe(topic, 0); // QoS 0 - 最多一次  QoS 1 - 至少一次   QoS 2 - 恰好一次
    } else {
      Serial.print("MQTT连接失败，错误代码: ");
      Serial.println(" 5秒后重试...");
      delay(5000);
    }
  }
}

void publishSensorData(float temperature,float humidity) {
  StaticJsonDocument<200> doc;
  doc["device"] = "ESP32_002";
  doc["temperature"] = String(temperature);
  doc["humidity"] = String(humidity);
  doc["timestamp"] = millis();
  
  // Serialize and publish
  mqttClient.beginMessage(topic, false, 0);// true表示保留消息  QoS 0 - 最多一次  QoS 1 - 至少一次   QoS 2 - 恰好一次
  serializeJson(doc, mqttClient);
  mqttClient.endMessage();
}

void onMessage(int messageSize) {
  Serial.println("Message received: ");
  String topic = mqttClient.messageTopic();
  
  String message = "";
  
  while (mqttClient.available()) {
    message += (char)mqttClient.read();
  }
  
  Serial.print("Message on '");
  Serial.print(topic);
  Serial.print("': ");
  Serial.println(message);
  Serial.println();
}

void readAndPublishSensorData() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  
  if (!isnan(temperature) && !isnan(humidity)) {
    char tempStr[8];
    char humStr[8];
    
    dtostrf(temperature, 6, 2, tempStr);
    dtostrf(humidity, 6, 2, humStr);
    
    Serial.printf("传感器数据已发布: 温度=%s°C, 湿度=%s%%\n", tempStr, humStr);
    //发布json格式温湿度数据
    publishSensorData(temperature,humidity);
  }
}

void setup() {
  Serial.begin(115200);
  setup_wifi();

  // 设置MQTT
  // Connect with will message
  // mqttClient.beginWill("arduino/status", 1, true, 1);
  // mqttClient.endWill();
  // Set callback
  mqttClient.onMessage(onMessage);
}

void loop() {
  if(WiFi.status() != WL_CONNECTED){
    setup_wifi();
  }
  if (!mqttClient.connected()) {
    reconnect();
  }
  mqttClient.poll();

  // 定期读取传感器数据
  if (millis() - lastSensorRead > sensorInterval) {
    Serial.println("定期读取传感器数据");
    lastSensorRead = millis();
    readAndPublishSensorData();
    Serial.println("mqtt消息已发布。");
  }
}
