#define BLINKER_WIFI
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP32httpUpdate.h>
#include <FS.h>
#include <SPIFFS.h>
#include <ESPmDNS.h>
#include <Ticker.h>
#include <WebServer.h>
#include <WiFi.h>
#include <Blinker.h>
#include <HTTPClient.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include "ESPmDNS.h"
#include <Ticker.h>
#include <Thread.h>
#include <WebServer.h>
#include <Arduino.h>

WiFiClient wificlient;
Thread myThread = Thread();
TFT_eSPI tft = TFT_eSPI();
String flash_file = "/false.txt";  //被读取的文件位置和名称
String flash_bl = "/bl.txt";
bool flash_bool = false;
char auth[] = "b07664fc1910";
String ssid;
String passwd;
String html;
bool heating = false;  //加热状态  true 正在加热  false 加热关闭
bool water = false;    //加水状态  true 正在加水  false 加水关闭
float waterT = 0.01;   //预设定水温
//SDA 15
//SCL 14
//CS  5
//DC  27
//RST 33
//BL  22
// 定义数据线引脚 p17
#define ONE_WIRE_BUS 17
#define P22 16  //加热开关

#define P21 21  //上水开关

#define touch4 4  //设置WIFI
#define m4 25

// 初始化 OneWire 总线对象
OneWire oneWire(ONE_WIRE_BUS);

// 初始化 DallasTemperature 对象
DallasTemperature sensors(&oneWire);

BlinkerNumber Number3("num-yev");  //水位

BlinkerNumber Number1("num-8sr");  //水温
BlinkerButton Button1("btn-x2p");  //刷新水温

BlinkerNumber Number2("num-yc4");  //预热水温
BlinkerButton Button2("btn-s73");  //刷新预热水温

BlinkerButton Button3("btn-8ft");  //手动加热开关
BlinkerButton Button4("btn-bx8");  //上水开关

BlinkerButton Button5("btn-4dx");  //刷新手动开关状态
BlinkerButton Button6("btn-ems");  //刷新上水开关状态

BlinkerText Text1("tex-qyx");  //显示加热开关或上水 状态

Ticker myTicker;
String flashWifi = "/wifi.txt";  //wifi密码存放文件
WebServer webServer;
int touchJu = 0;
int touchJr = 2;
#define baudRate 115200
void niceCallback() {
  String HI = esp32getHI();
  Serial.println(HI);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.setCursor(10, 10, 2);  //设置起始坐标(10, 10)，1 号字体
  tft.println(HI);           //显示文字
  millis();
}
void setup(void) {
  pinMode(P22, OUTPUT);
  pinMode(P21, OUTPUT);
  //水位探测
  pinMode(m4, INPUT_PULLUP);

  pinMode(touchJr, INPUT_PULLUP);
  pinMode(touchJu, INPUT_PULLUP);
  digitalWrite(P22, LOW);
  digitalWrite(P21, LOW);
  myThread.onRun(niceCallback);
  myThread.setInterval(10000);
  Serial.begin(baudRate);
  delay(200);
  SPIFFS.begin();
  delay(200);
  if (FlashConnetWifi() == false) {
    HtmlSetWifi();
  }
  WiFi.disconnect();
  delay(300);
  Blinker.begin(auth, ssid.c_str(), passwd.c_str());
  Button1.attach(button1_callback);  //刷新水温
  Button2.attach(button2_callback);  //刷新预热水温
  Button3.attach(button3_callback);  //手动加热开关
  Button4.attach(button4_callback);  //上水开关
  Button5.attach(button5_callback);  //刷新手动开关状态
  Button6.attach(button6_callback);  //刷新上水开关状态
  Blinker.attachData(dataRead);

  SPIFFS.begin();
  if (SPIFFS.exists(flash_file) == false) {
    File dataFile = SPIFFS.open(flash_file, "w");
    dataFile.println("27.00");
    waterT = 27.00;
    dataFile.close();
  } else {
    SPIFFS.begin();
    File dataFile = SPIFFS.open(flash_file, "r");
    String result = dataFile.readString();
    result.trim();
    waterT = result.toFloat();
  }

  if (SPIFFS.exists(flash_bl) == false) {
    File dataFile = SPIFFS.open(flash_bl, "w");
    dataFile.println("false");
    dataFile.close();
  } else {
    SPIFFS.begin();
    File dataFile = SPIFFS.open(flash_bl, "r");
    String result = dataFile.readString();
    result.trim();
    if (result == "true") {
      digitalWrite(P22, HIGH);
      heating = true;
      flash_bool = true;
    }
  }
  tft.init();
  tft.fillScreen(TFT_BLACK);  //屏幕颜色
  tft.setCursor(10, 60, 2);
  tft.println("  x % ");
  String re = sendPostRequest();
  if (re.length() > 10) {
    re.trim();
    t_httpUpdate_return ret = ESPhttpUpdate.update(re);
  }
  // 初始化DS18B20传感器
  sensors.begin();
}

void loop(void) {
  Blinker.run();
  // 获取温度数据
  sensors.requestTemperatures();
  // 读取温度
  float temperature = sensors.getTempCByIndex(0);
  tft.setCursor(10, 40, 2);

  tft.println(String(temperature) + " ° C");
  if (temperature >= waterT) {
    digitalWrite(P22, LOW);
    heating = false;
    if (flash_bool == false) {
      SPIFFS.begin();
      File dataFile = SPIFFS.open(flash_bl, "w");
      dataFile.println("false");
      dataFile.close();
      flash_bool = true;
    }

    Serial.println("达到设定温度 关闭加热");
  }
  //delay(1000);
  if (digitalRead(m4) == LOW) {
    Serial.println("100");
    Number3.print(100);
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.setCursor(10, 60, 2);
    tft.println("100 % ");
    if (water == true) {
      water = false;
      digitalWrite(P21, LOW);
      tft.setCursor(10, 80, 2);
      tft.println("water off");
      Text1.print("加水已经关闭");
      Button4.color("#000000");
      Button4.text("加水已关");
      Button4.print();
    }
  } else {
    if (water == false) {
      Number3.print(10);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setCursor(10, 60, 2);
      tft.println("  x % ");
    }
  }
  if (myThread.shouldRun()) {
    myThread.run();
  }

  if (digitalRead(touchJu) == LOW) {
    if (water == false) {
      water = true;
      digitalWrite(P21, HIGH);
      Text1.print("正在加水...");
      Button4.color("#00FF00");
      Button4.text("正在加水");
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setCursor(10, 80, 2);
      tft.println("water on ");
    } else {
      water = false;
      digitalWrite(P21, LOW);
      Text1.print("加水已经关闭");
      Button4.color("#000000");
      Button4.text("加水 关");
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setCursor(10, 80, 2);
      tft.println("water off");
    }
    Button4.print();
  }
  if (digitalRead(touchJr) == LOW) {
    SPIFFS.begin();
    if (heating == false) {
      heating = true;
      digitalWrite(P22, HIGH);
      if (flash_bool == false) {
        File dataFile = SPIFFS.open(flash_bl, "w");
        dataFile.println("true");
        dataFile.close();
        flash_bool = true;
      }
      Text1.print("正在加热...");
      Button3.color("#00FF00");
      Button3.text("加热开");
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setCursor(10, 100, 2);
      tft.println("hot on ");
    } else {
      heating = false;
      digitalWrite(P22, LOW);

      if (flash_bool == true) {
        File dataFile = SPIFFS.open(flash_bl, "w");
        dataFile.println("false");
        dataFile.close();
        flash_bool = false;
      }
      Text1.print("加热已经关闭");
      Button3.color("#000000");
      Button3.text("加热已关");
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setCursor(10, 100, 2);
      tft.println("hot off");
    }
    Button3.print();
  }
}
//刷新水温
void button1_callback(const String& state) {
  //BLINKER_LOG("get button state: ", state);
  sensors.requestTemperatures();
  float temperature = sensors.getTempCByIndex(0);
  Number1.print(temperature);
  Text1.print(temperature);
}
//刷新预热水温
void button2_callback(const String& state) {
  //BLINKER_LOG("get button state: ", state);
  SPIFFS.begin();
  File dataFile = SPIFFS.open(flash_file, "r");
  String result = dataFile.readString();
  result.trim();  //清理字符两边的空格
  Number2.print(result.toFloat());
  Serial.print(result);
}
//手动加热开关
void button3_callback(const String& state) {
  //BLINKER_LOG("get button state: ", state);
  SPIFFS.begin();
  if (heating == false) {
    heating = true;
    digitalWrite(P22, HIGH);
    if (flash_bool == false) {
      File dataFile = SPIFFS.open(flash_bl, "w");
      dataFile.println("true");
      dataFile.close();
      flash_bool = true;
    }
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.setCursor(10, 100, 2);
    tft.println("hot on ");
    Text1.print("正在加热...");
    Button3.color("#00FF00");
    Button3.text("加热开");
  } else {
    heating = false;
    digitalWrite(P22, LOW);

    if (flash_bool == true) {
      File dataFile = SPIFFS.open(flash_bl, "w");
      dataFile.println("false");
      dataFile.close();
      flash_bool = false;
    }
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.setCursor(10, 100, 2);
    tft.println("hot off");
    Text1.print("加热已经关闭");
    Button3.color("#000000");
    Button3.text("加热已关");
  }
  Button3.print();
}
//上水开关
void button4_callback(const String& state) {
  // BLINKER_LOG("get button state: ", state);
  if (water == false) {
    water = true;
    digitalWrite(P21, HIGH);
    Text1.print("正在加水...");
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.setCursor(10, 80, 2);
    tft.println("water on ");
    Button4.color("#00FF00");
    Button4.text("正在加水");
  } else {
    water = false;
    digitalWrite(P21, LOW);
    Text1.print("加水已经关闭");
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.setCursor(10, 80, 2);
    tft.println("water off");
    Button4.color("#000000");
    Button4.text("加水 关");
  }
  Button4.print();
}
//刷新手动加热开关状态
void button5_callback(const String& state) {
  //BLINKER_LOG("get button state: ", state);
  if (heating == true) {
    Text1.print("正在加热...");
    Button3.color("#00FF00");
    Button3.text("加热 开");
  } else {
    Button3.color("#000000");
    Button3.text("加热 关");
    Text1.print("加热已经关闭");
  }
  Button3.print();
}
//刷新上水开关状态
void button6_callback(const String& state) {
  //BLINKER_LOG("get button state: ", state);
  if (water == true) {
    Button4.color("#00FF00");
    Button4.text("开");
    Text1.print("正在加水...");
  } else {
    Button4.color("#000000");
    Button4.text("加水 关");
    Text1.print("加水已经关闭");
  }
  Button4.print();
}

// 如果未绑定的组件被触发，则会执行其中内容
void dataRead(const String& data) {
  BLINKER_LOG("Blinker readString: ", data);
  float tmp = data.toFloat();

  if (tmp == 0) {
    Text1.print("失败,只能数字");
  } else {
    File dataFile = SPIFFS.open(flash_file, "w");
    dataFile.println(data);
    waterT = tmp;
    dataFile.close();
    Text1.print("预制温度 " + data);
  }
}

void espReboot() {
  ESP.restart();
}



String sendPostRequest() {
  HTTPClient http;
  String url = "http://jyan.nobiggie.cn/arduino/vs";
  http.begin(wificlient, url);
  http.setTimeout(3000);
  String postStr = "vs=a13544957057";
  char dataBuff[postStr.length()];
  strcpy(dataBuff, postStr.c_str());
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  int httpResponseCode = http.POST(dataBuff);
  if (httpResponseCode > 0) {
    String response = http.getString();
    return response;
  }
  return "";
}

String esp32getHI() {
  HTTPClient http;
  String response;
  String urlstr = "http://jyan.nobiggie.cn/arduino/hi";
  http.begin(wificlient, urlstr);
  http.setTimeout(3000);
  int httpCode = http.GET();
  // httpCode will be negative on error
  if (httpCode == 200) {
    response = http.getString();
    return response;
  } else {
    return "";
  }
  http.end();
}


void HtmlSetWifi() {
  WifiScan();
  apStart();
  delay(1000);
  Serial.println("start webserver");
  //5分后重启 防止停电后复电，路由器连接WIFI速度慢于ESP导致ESP连接不到路由器进入无限AP模式，所以这里只让AP激活5分钟后就重启
  myTicker.once(300, espReboot);
  delay(200);
  webserverStart();
  while (1) {
    webServer.handleClient();  //检查网络服务请求并处理
  }
}
void WifiScan() {
  WiFi.disconnect();
  Serial.begin(baudRate);
  WiFi.mode(WIFI_STA);
  delay(100);
  int n = WiFi.scanNetworks();
  if (n > 0) {
    String a = "附近WiFi <select id=\"ssid\">";
    for (int i = 0; i < n; i++) {
      Serial.println(WiFi.SSID(i));
      a = a + "<option value=\"" + WiFi.SSID(i) + "\">" + WiFi.SSID(i) + "</option>";
      delay(50);
    }
    String HtmlStart = String("") + "<!DOCTYPE html>" + "<html>" + "<head>" + "<meta charset=\"utf-8\">" + "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\" />" + "<title>设置WiFi</title>" + "<link rel=\"stylesheet\" href=\"\">" + "</head>" + "<script>" + "onload  = function() {" + "document.getElementById(\"up\").onclick = function(){" + "var ssida=document.getElementById(\"ssid\").value;" + "var ssid=ssida.replace(/\\s+/g, \" \");" + "var passwda=document.getElementsByTagName('input')[0].value;" + "var passwd=passwda.replace(/\\s+/g, \" \");" + "xhr = new XMLHttpRequest();" + "xhr.open(\"POST\",\"./setWifi\",true);" + "var posts = (\"ssid=\"+ssid+\"&passwd=\"+ passwd);" + "xhr.setRequestHeader(\"Content-Type\",\"application/x-www-form-urlencoded\");" + "xhr.send(posts);" + "xhr.onreadystatechange = function(){" + "if(this.readyState == 4 && this.status == 200){" + "alert(this.responseText);" + "}" + "}" + "}" + "}" + "</script>" + "<body>";
    String HtmlEnd = String("") + "<p>WiFi密码<input type=\"text\" id=\"passwd\"></p>" + "<input type=\"submit\" id=\"up\" value=\"设 置\">" + "<hr/>" + "<div>如果附近WiFi没有显示到自己的WIFI<div>" + "<div>请重启或离信号近点</div>" + "<div>连接成功AP热点退出转WIFI_STA</div>" + "</body>" + "</html>";
    a = a + "</select>";
    html = HtmlStart + a + HtmlEnd;
  } else {
    html = "扫描不到网络";
  }
}
void setWifi() {
  ssid = webServer.arg(0);
  passwd = webServer.arg(1);
  const char* Ssid = ssid.c_str();
  const char* Passwd = passwd.c_str();
  String sp = ssid + "&" + passwd;
  Serial.println(sp);
  Serial.begin(baudRate);
  delay(500);
  WiFi.begin(Ssid, Passwd);
  WiFi.mode(WIFI_STA);
  delay(200);
  Serial.println("wifi_connet");
  int ii = 0;
  for (ii; ii < 20; ii++) {
    delay(500);
    Serial.print(".");
    if (WiFi.status() == WL_CONNECTED) {
      webServer.send(200, "text/plane", "Wifi密码正确,ESP准备重启");
      webServer.close();
      delay(500);
      WiFi.disconnect();
      delay(500);
      //写入数据
      SPIFFS.format();
      delay(500);
      SPIFFS.begin();
      File dataFile = SPIFFS.open(flashWifi, "w");
      dataFile.println(sp);
      dataFile.close();
      Serial.println("HTML设置网络连接成功");
      delay(500);
      ESP.restart();
    }
  }
  webServer.send(200, "text/plane", "Wifi密码错误,请重新输入");
}
//------- 展示页面-------
void handleRoot() {
  webServer.send(500, "text/html", html);
}
void handleNotFound(void) {
  webServer.send(404, "text/plain", "404-The page is not Found!");
}
void apStart() {
  Serial.begin(baudRate);
  WiFi.mode(WIFI_AP);
  IPAddress local_IP(192, 168, 168, 2);
  IPAddress gateway(192, 168, 168, 1);
  IPAddress subnet(255, 255, 255, 0);
  WiFi.softAPConfig(local_IP, gateway, subnet);
  //启动AP模式，并设置账号和密码
  boolean result = WiFi.softAP("192.168.168.2", "nobiggie.cn");
  if (result) {
    Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP());
  }
}
void webserverStart() {
  webServer.begin(80);            // 启用网络服务
  webServer.on("/", handleRoot);  // / 在HTTP中，表示请求首页服务，
  webServer.on("/setWifi", setWifi);
  webServer.onNotFound(handleNotFound);  // 当服务器没找到所需的服务，调用404函数
  Serial.println("webserver started");
}
bool FlashConnetWifi() {
  Serial.begin(baudRate);
  delay(200);
  SPIFFS.begin();
  if (SPIFFS.exists(flashWifi) == false) {
    Serial.println("NOT FOUND");
    return false;
  }

  File dateFile = SPIFFS.open(flashWifi, "r");
  String result;
  for (int i = 0; i < dateFile.size(); i++) {
    //Serial.print((char)dateFile.read());
    result += (char)dateFile.read();
  }
  result.trim();
  Serial.println(result);
  int i = result.indexOf("&");
  String wifiname = result.substring(0, i);
  String wifipw = result.substring(i + 1);
  const char* WifiName = wifiname.c_str();
  const char* WifiPw = wifipw.c_str();
  Serial.println(WifiName);
  Serial.println(WifiPw);
  WiFi.begin(WifiName, WifiPw);
  delay(500);
  WiFi.mode(WIFI_STA);
  Serial.println("FlashConnet...");
  int ii = 0;
  for (ii; ii < 30; ii++) {
    delay(500);
    Serial.print(" . ");
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("flash connet success");
      ssid = String(WifiName);
      passwd = String(WifiPw);
      return true;
    }
  }
  Serial.println("flash read error");
  return false;
}