//马达开            马达开
//马达关            马达关
//马达运行时间      马达时间
//马达开关次数      马达次数
//当前时间          北京时间
#include "Arduino.h"
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
// 定义LED引脚
#define DHTPIN D4       //说明数据接口为8266开发板的D4口，也可以写为#define DHTPIN 2既8266芯片的IO口2
const int second = 30;  //定时频率
// 新增变量：程序开始时间
unsigned long programStartTime = 0;
// 新增变量：亮灯次数
unsigned long ledOnCount = 0;
// 新增变量：累计亮灯时间
unsigned long totalLedOnTime = 0;
// 休眠时间
const int night = 20;
const int morning = 6;

// 定义时间间隔（毫秒）
const unsigned long intervalOn = 600000;
const unsigned long intervalOff = 3000000;

// 变量用于存储上次LED状态改变的时间
unsigned long previousMillis = 0;
// 变量用于跟踪LED当前状态
bool ledState = HIGH;
//抽水马达状态
const char *kai = "马达打开中";
const char *guan = "马达关闭中";

//定义WIFI信息
const char *ssid = "CU_A9TU";       // Enter SSID here
const char *password = "452131wW";  //Enter Password here

// MQTT Broker Settings
const char *mqtt_broker = "192.168.3.24";
const char *mqtt_topic = "/device/esp8266/001";
const char *mqtt_username = "wenfei";
const char *mqtt_password = "452131wW";
const int mqtt_port = 1883;  //端口

Ticker myTicker;

WiFiClient espClient;
PubSubClient mqtt_client(espClient);

//北京时间校准
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
String currentTime;
String openTime;

//发送抽水马达状态
void sendMadaStatus(const char *str) {
  if(mqtt_client.connected()) {
    mqtt_client.publish(mqtt_topic, str);
    timeClient.update();
    Serial.println(timeClient.getFormattedTime());
    Serial.println(str);
  }
}

// 新增定时器回调函数
void timerCallback() {
  timeClient.update();
  currentTime = timeClient.getFormattedTime();
  String hours = currentTime.substring(0, 2);
  int hour = hours.toInt();
  //判断是否处于休眠时间段
  Serial.println(hour);
  if ((hour >= night) || (hour < morning)) {
    Serial.println("sleeping");
    if(ledState == LOW) {
      // 关闭LED
      ledState = HIGH;
      digitalWrite(D4, ledState);
    }
    // 这里可以添加休眠代码，例如ESP32的深度睡眠
    //ESP.deepSleep(1 * 60 * 1000000); // 休眠30秒
    return;
  }
  // 获取当前时间
  Serial.println("aliving");
  unsigned long currentMillis = millis();
  if (ledState == HIGH) {
    // 如果LED当前是关闭状态，检查是否到了打开的时间
    if (currentMillis - previousMillis >= intervalOff) {
      // 记录上次状态改变的时间
      previousMillis = currentMillis;
      ledState = LOW;
      digitalWrite(D4, ledState);
      sendMadaStatus(kai);
      timeClient.update();
      currentTime = timeClient.getFormattedTime();
      sendMadaStatus(currentTime.c_str());
    }
  } else {
    // 如果LED当前是打开状态，检查是否到了关闭的时间
    if (currentMillis - previousMillis >= intervalOn) {
      // 增加亮灯次数
      ledOnCount++;
      // 累计亮灯时间
      totalLedOnTime += intervalOn;
      // 记录上次状态改变的时间
      previousMillis = currentMillis;
      ledState = HIGH;
      digitalWrite(D4, ledState);
      sendMadaStatus(guan);
      timeClient.update();
      currentTime = timeClient.getFormattedTime();
      sendMadaStatus(currentTime.c_str());
    }
  }
}
//长时间断后  再开启WIFI无法连接的问题
void connectToWiFi() {
  Serial.println("Connecting to ");
  Serial.println(ssid);
  //connect to your local wi-fi network
  WiFi.begin(ssid, password);
  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");
  Serial.println(WiFi.localIP());
}
void connectToMQTT() {
  while (!mqtt_client.connected()) {
    String client_id = "esp8266-client-" + String(WiFi.macAddress());
    Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());
    if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
      Serial.println("Connected to MQTT broker");
      timeClient.update();
      openTime = timeClient.getFormattedTime();
      mqtt_client.subscribe(mqtt_topic);
      mqtt_client.publish(mqtt_topic, openTime.c_str());  // Publish message upon successful connectionc_str()
    } else {
      Serial.print("Failed, rc=");
      Serial.print(mqtt_client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}
void mqttCallback(char *mqtt_topic, byte *payload, unsigned int length) {
  String str;
  Serial.print("Message received on mqtt_topic: ");
  Serial.println(mqtt_topic);
  Serial.print("Message: ");
  for (unsigned int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    str += (char)payload[i];
  }
  //马达开
  if (str == "马达开") {
    digitalWrite(D4, LOW);
    sendMadaStatus(kai);
  }
  //马达关
  if (str == "马达关") {
    digitalWrite(D4, HIGH);
    sendMadaStatus(guan);
  }
  //马达运行时间
  if (str == "马达时间") {
    sendMadaStatus(((String)totalLedOnTime).c_str());
  }
  //马达开关次数
  if (str == "马达次数") {
    sendMadaStatus(((String)ledOnCount).c_str());
  }
  //当前时间
  if (str == "北京时间") {
    timeClient.update();
    currentTime = timeClient.getFormattedTime();
    sendMadaStatus(currentTime.c_str());
  }
  // if(str=="重启")
  // {
  //   esp_restart();
  // }
  if (str == "状态") {
    String maDa = "";
    if(ledState == LOW) {
      maDa = "马达关";
    } else {
      maDa = "马达开";
    }
    timeClient.update();
    currentTime = timeClient.getFormattedTime();
    String maDaStatus = "";
    maDaStatus = "当前时间" + currentTime;
    //马达状态
    maDaStatus += ("\n 开机时间: " + openTime);
    maDaStatus += ("\n 马达状态: " + maDa);
    maDaStatus += ("\n 马达累计运行时间: " + (String)(totalLedOnTime / 1000) + "秒");
    maDaStatus += ("\n 马达累计运行次数: " + (String)ledOnCount);
    sendMadaStatus(maDaStatus.c_str());
  }
  if (str == "help") {
    String help = "help      马达开        马达关         马达时间          马达次数         北京时间          状态      重启   ";
    sendMadaStatus(help.c_str());
  }
  Serial.println("\n-----------------------");
  Serial.println(str);
}

void setup() {
  Serial.begin(115200);
  Serial.print("开机成功");
  // 记录程序开始时间
  programStartTime = millis();
  // 将LED引脚设置为输出模式
  pinMode(D4, INPUT);
  ledState = HIGH;
  digitalWrite(D4, HIGH);
  // 假设使用Arduino的定时器库，这里简单模拟启动定时器
  // 实际使用时需要根据具体定时器库修改
  // 这里假设每1000ms调用一次定时器回调函数
  myTicker.attach(second, timerCallback);  // Call callbackFunction every 1 second
  ///连接WIFI
  connectToWiFi();
  // Set Root CA certificate
  //espClient.setCACert(ca_cert);
  // 初始化NTP客户端
  timeClient.begin();
  // 设置时区偏移量，例如北京时间为 +8 小时，单位为秒
  timeClient.setTimeOffset(28800);
  timeClient.update();
  openTime = timeClient.getFormattedTime();
  ///mqtt连接
  mqtt_client.setServer(mqtt_broker, mqtt_port);
  mqtt_client.setKeepAlive(60);
  mqtt_client.setCallback(mqttCallback);  // Corrected callback function name
  connectToMQTT();
}

void loop() {
  mqtt_client.loop();
  delay(10000);
  //连接WIFI
  if (WiFi.status() != WL_CONNECTED) {
    connectToWiFi();
  }
  if (WiFi.status() == WL_CONNECTED) {
    //连接mqtt
    if (!mqtt_client.connected()) {
      connectToMQTT();
    }
  }
}