|
经常坐在电脑面前打游戏工作的时候,打开天猫精灵广告多,步骤麻烦,语音设别率低。所以就打算搞了这么一个东西。
可以在电脑或者手机浏览器直接控制空调和风扇就很方便。
控制方法。有两种输入ESP8266的ip地址就直接跳转到控制面板。
还有就是安装浏览器扩展,设置好ESP8266的ip就可以直接控制
浏览器扩展
完整源码.zip
(264.83 KB, 下载次数: 25)
- #include "IR-AC-control.h"
- #if defined(ESP8266)
- #include <ESP8266WiFi.h>
- #include <ESP8266mDNS.h>
- #include <ESP8266HTTPUpdateServer.h>
- #include <ESP8266WebServer.h>
- #endif // ESP8266
- #if defined(ESP32)
- #include <ESPmDNS.h>
- #include <WebServer.h>
- #include <WiFi.h>
- #include <Update.h>
- #endif // ESP32
- //天气
- #include <Ticker.h>
- #include <ESP8266HTTPClient.h>
- #include <WiFiClientSecureBearSSL.h>
- #include <NTPClient.h>
- //天气
- #include <WiFiUdp.h>
- #include <WiFiManager.h>
- #include <ArduinoJson.h>
- #include <IRremoteESP8266.h>
- #include <IRsend.h>
- #include <ArduinoOTA.h>
- //空调品牌设置 可以修改成自己空调品牌的.h文件和静态变量,IRremoteESP8266库里面可以找到
- #include "ir_Gree.h"
- #define AUTO_MODE kGreeAuto
- #define COOL_MODE kGreeCool
- #define DRY_MODE kGreeDry
- #define HEAT_MODE kGreeHeat
- #define FAN_MODE kGreeFan
- #define FAN_AUTO kGreeFanAuto
- #define FAN_MIN kGreeFanMin
- #define FAN_MED kGreeFanMed
- #define FAN_HI kGreeFanMax
- //空调品牌
- const uint16_t kIrLed = 4;
- IRGreeAC ac(kIrLed);
- IRsend irsend(kIrLed);
- //天气
- Ticker ticker;
- int count, old_h;
- bool check_temp; //气温检查开关。晚点到一定的气温,会关闭风扇,晚上睡觉经常谁到感冒,要申请高德天气key才可以使用
- WiFiUDP ntpUDP;
- NTPClient timeClient(ntpUDP, "ntp1.aliyun.com", 60 * 60 * 8, 30 * 60 * 1000);
- int temparr[5] = {3, 4, 5, 6, 7};//检查气温的时间
- int openTemp;
- //天气
- struct state
- {
- uint8_t Swingmode = 1, temperature = 27, fan = 0, operation = 1;
- bool powerStatus;
- };
- uint16_t fanPower[191] = {1166, 432, 1164, 462, 314, 1312, 1110, 490, 1136, 462, 314, 1312, 314, 1310, 316, 1312, 314, 1310, 314, 1310, 314, 1312, 1138, 7014, 1164, 462, 1138, 462, 314, 1310, 1138, 462, 1138, 462, 316, 1286, 340, 1284, 338, 1290, 338, 1284, 340, 1286, 338, 1312, 1138, 7014, 1166, 486, 1140, 512, 316, 1310, 1138, 488, 1138, 462, 314, 1288, 338, 1286, 340, 1284, 340, 1284, 342, 1284, 340, 1288, 1162, 7014, 1164, 488, 1136, 464, 314, 1284, 1164, 462, 1138, 438, 338, 1284, 342, 1282, 342, 1284, 342, 1284, 340, 1286, 342, 1284, 1164, 7014, 1138, 466, 1164, 436, 340, 1286, 1164, 436, 1164, 462, 340, 1282, 344, 1284, 342, 1284, 342, 1282, 342, 1284, 342, 1284, 1166, 7016, 1136, 462, 1164, 436, 342, 1284, 1164, 436, 1138, 462, 342, 1284, 340, 1286, 340, 1286, 338, 1288, 340, 1286, 316, 1308, 1162, 7016, 1162, 464, 1162, 490, 314, 1312, 1160, 440, 1164, 462, 310, 1312, 312, 1314, 312, 1314, 312, 1314, 312, 1314, 312, 1312, 1162, 7018, 1162, 438, 1160, 460, 316, 1290, 1160, 488, 1138, 462, 314, 1314, 314, 1310, 314, 1312, 314, 1310, 316, 1310, 314, 1312, 1138};
- uint16_t fanSleep[143] = {1166, 482, 1138, 486, 316, 1336, 1138, 486, 1140, 486, 316, 1308, 316, 1286, 340, 1308, 316, 1310, 314, 1310, 1136, 490, 316, 7840, 1164, 486, 1114, 510, 316, 1310, 1138, 512, 1138, 486, 316, 1284, 342, 1286, 340, 1286, 340, 1310, 314, 1310, 1138, 488, 314, 7838, 1164, 486, 1140, 486, 316, 1310, 1138, 512, 1138, 488, 316, 1312, 314, 1282, 342, 1312, 316, 1286, 340, 1312, 1138, 486, 316, 7864, 1166, 486, 1138, 488, 314, 1286, 1164, 512, 1138, 488, 314, 1284, 342, 1284, 342, 1312, 340, 1284, 342, 1284, 1164, 514, 314, 7842, 1164, 514, 1138, 486, 316, 1284, 1166, 514, 1114, 512, 314, 1284, 342, 1284, 342, 1284, 344, 1280, 344, 1282, 1166, 458, 342, 7838, 1164, 486, 1164, 460, 342, 1282, 1140, 484, 1166, 460, 342, 1308, 340, 1286, 340, 1286, 340, 1312, 342, 1310, 1172, 452, 344};
- uint16_t fanSwing[143] = {1166, 484, 1112, 512, 316, 1336, 1136, 516, 1126, 500, 314, 1310, 316, 1310, 1112, 514, 314, 1312, 314, 1312, 314, 1308, 316, 7838, 1164, 486, 1138, 462, 314, 1308, 1140, 486, 1138, 488, 316, 1308, 316, 1312, 1138, 486, 316, 1310, 342, 1310, 314, 1310, 316, 7838, 1138, 540, 1116, 510, 316, 1310, 1140, 486, 1138, 486, 316, 1312, 316, 1310, 1114, 512, 316, 1312, 314, 1312, 314, 1310, 316, 7838, 1166, 512, 1116, 510, 316, 1288, 1160, 486, 1116, 510, 316, 1310, 316, 1336, 1116, 510, 316, 1312, 314, 1336, 314, 1292, 336, 7840, 1138, 514, 1116, 510, 316, 1288, 1138, 510, 1116, 510, 316, 1286, 342, 1288, 1136, 514, 316, 1314, 338, 1286, 340, 1310, 340, 7842, 1138, 540, 1114, 510, 316, 1284, 1138, 516, 1138, 488, 316, 1284, 342, 1286, 1136, 516, 314, 1286, 340, 1312, 340, 1284, 342};
- uint16_t fanMode[143] = {1166, 484, 1168, 458, 316, 1310, 1138, 462, 1138, 486, 314, 1310, 316, 1308, 314, 1310, 316, 1310, 1166, 460, 314, 1310, 314, 7862, 1166, 436, 1164, 488, 314, 1310, 1138, 488, 1136, 490, 314, 1310, 316, 1310, 314, 1312, 314, 1310, 1138, 488, 314, 1310, 316, 7840, 1160, 486, 1116, 510, 316, 1310, 1136, 486, 1140, 486, 314, 1310, 316, 1310, 314, 1308, 316, 1310, 1138, 488, 314, 1310, 316, 7838, 1162, 488, 1138, 488, 314, 1312, 1140, 460, 1188, 462, 316, 1308, 316, 1310, 316, 1312, 314, 1310, 1138, 488, 316, 1284, 340, 7840, 1162, 492, 1134, 492, 314, 1286, 1164, 486, 1114, 512, 316, 1338, 312, 1312, 314, 1312, 316, 1284, 1162, 490, 316, 1312, 314, 7842, 1162, 516, 1110, 518, 316, 1288, 1160, 466, 1156, 492, 316, 1286, 338, 1338, 314, 1310, 314, 1286, 1160, 492, 316, 1284, 342};
- File fsUploadFile;
- state acState;
- char deviceName[] = "AC Remote Control";
- #if defined(ESP8266)
- ESP8266WebServer server(80);
- ESP8266HTTPUpdateServer httpUpdateServer;
- #endif // ESP8266
- #if defined(ESP32)
- WebServer server(80);
- #endif // ESP32
- //天气
- void updateTime()
- {
- timeClient.update();
- Serial.print("校准时间");
- Serial.println(timeClient.getFormattedTime());
- }
- void tickerCount()
- {
- count++;
- }
- void getTemp()
- {
- std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
- client->setInsecure();
- HTTPClient https;
- if (https.begin(*client, "https://restapi.amap.com/v3/weather/weatherInfo?city=450105&key=高德天气key"))
- { // HTTPS
- int httpCode = https.GET();
- if (httpCode > 0)
- {
- Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
- if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
- {
- String payload = https.getString();
- Serial.println(payload);
- StaticJsonDocument<512> doc;
- DeserializationError error = deserializeJson(doc, payload);
- if (error)
- {
- Serial.print(F("deserializeJson() failed: "));
- Serial.println(error.f_str());
- return;
- }
- JsonObject lives_0 = doc["lives"][0];
- const char *info_weather = lives_0["weather"]; // "多云"
- int temperature = lives_0["temperature"].as<int>();
- if (temperature <= openTemp)
- {
- int currentHour = timeClient.getHours();
- int i = 0;
- while (i <= 5)
- {
- if (temparr[i] == currentHour)
- {
- irsend.sendRaw(fanPower, 191, 38);
- Serial.println("条件满足");
- }
- i++;
- }
- }
- check_temp = true;
- }
- }
- else
- {
- Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
- }
- https.end();
- }
- else
- {
- Serial.printf("[HTTPS] Unable to connect\n");
- }
- }
- //天气
- bool handleFileRead(String path)
- {
- if (path.endsWith("/"))
- path += "index.html";
- String contentType = getContentType(path);
- String pathWithGz = path + ".gz";
- if (FILESYSTEM.exists(pathWithGz) || FILESYSTEM.exists(path))
- {
- if (FILESYSTEM.exists(pathWithGz))
- path += ".gz";
- File file = FILESYSTEM.open(path, "r");
- server.streamFile(file, contentType);
- file.close();
- return true;
- }
- return false;
- }
- String getContentType(String filename)
- {
- if (filename.endsWith(".html"))
- return "text/html";
- else if (filename.endsWith(".css"))
- return "text/css";
- else if (filename.endsWith(".js"))
- return "application/javascript";
- else if (filename.endsWith(".ico"))
- return "image/x-icon";
- else if (filename.endsWith(".gz"))
- return "application/x-gzip";
- return "text/plain";
- }
- void handleFileUpload()
- {
- HTTPUpload &upload = server.upload();
- if (upload.status == UPLOAD_FILE_START)
- {
- String filename = upload.filename;
- if (!filename.startsWith("/"))
- filename = "/" + filename;
- fsUploadFile = FILESYSTEM.open(filename, "w");
- filename = String();
- }
- else if (upload.status == UPLOAD_FILE_WRITE)
- {
- if (fsUploadFile)
- fsUploadFile.write(upload.buf, upload.currentSize);
- }
- else if (upload.status == UPLOAD_FILE_END)
- {
- if (fsUploadFile)
- {
- fsUploadFile.close();
- server.sendHeader("Location", "/success.html");
- server.send(303);
- }
- else
- {
- server.send(500, "text/plain", "500: couldn't create file");
- }
- }
- }
- void handleNotFound()
- {
- String message = "File Not Found\n\n";
- message += "URI: ";
- message += server.uri();
- message += "\nMethod: ";
- message += (server.method() == HTTP_GET) ? "GET" : "POST";
- message += "\nArguments: ";
- message += server.args();
- message += "\n";
- for (uint8_t i = 0; i < server.args(); i++)
- {
- message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
- }
- server.send(404, "text/plain", message);
- }
- void setup()
- {
- Serial.begin(115200);
- Serial.println();
- ac.begin();
- delay(1000);
- Serial.println("mounting " FILESYSTEMSTR "...");
- if (!FILESYSTEM.begin())
- {
- return;
- }
- WiFiManager wifiManager;
- if (!wifiManager.autoConnect(deviceName))
- {
- delay(3000);
- ESP.restart();
- delay(5000);
- }
- #if defined(ESP8266)
- httpUpdateServer.setup(&server);
- #endif // ESP8266
- //设置空调
- server.on("/state", HTTP_POST, []()
- {
- DynamicJsonDocument root(1024);
- DeserializationError error = deserializeJson(root, server.arg("plain"));
- if (error) {
- server.send(404, "text/plain", "FAIL. " + server.arg("plain"));
- } else {
- if (root.containsKey("temp")) {
- acState.temperature = (uint8_t) root["temp"];
- }
- if (root.containsKey("fan")) {
- acState.fan = (uint8_t) root["fan"];
- }
- if (root.containsKey("power")) {
- acState.powerStatus = root["power"];
- }
- if (root.containsKey("mode")) {
- acState.operation = root["mode"];
- }
- if (root.containsKey("Swingmode")) {
- acState.Swingmode = (uint8_t) root["Swingmode"];
- }
- String output;
- serializeJson(root, output);
- server.send(200, "text/plain", output);
- delay(200);
- if (acState.powerStatus) {
- ac.on();
- ac.setTemp(acState.temperature);
- if (acState.operation == 0) {
- ac.setMode(AUTO_MODE);
- ac.setFan(FAN_AUTO);
- acState.fan = 0;
- } else if (acState.operation == 1) {
- ac.setMode(COOL_MODE);
- } else if (acState.operation == 2) {
- ac.setMode(DRY_MODE);
- } else if (acState.operation == 3) {
- ac.setMode(HEAT_MODE);
- } else if (acState.operation == 4) {
- ac.setMode(FAN_MODE);
- }
- if (acState.operation != 0) {
- if (acState.fan == 0) {
- ac.setFan(FAN_AUTO);
- } else if (acState.fan == 1) {
- ac.setFan(FAN_MIN);
- } else if (acState.fan == 2) {
- ac.setFan(FAN_MED);
- } else if (acState.fan == 3) {
- ac.setFan(FAN_HI);
- }
- if (acState.Swingmode == 1 || acState.Swingmode == 11 || acState.Swingmode == 9 || acState.Swingmode == 7 ) {
- ac.setSwingVertical(true, acState.Swingmode);
- } else {
- ac.setSwingVertical(false, acState.Swingmode);
- }
- }
- } else {
- ac.off();
- }
- ac.send();
- } });
- //风扇
- server.on("/fan", HTTP_GET, []()
- {
- if (server.arg("state") =="0")
- {
- irsend.sendRaw(fanPower, 191, 38);
- }
- else if (server.arg("state") == "1")
- {
- irsend.sendRaw(fanSwing, 143, 38);
- }
- else if (server.arg("state") == "2")
- {
- irsend.sendRaw(fanMode, 143, 38);
- }
- else if (server.arg("state") == "3")
- {
- irsend.sendRaw(fanSleep, 143, 38);
- }
- server.send(200, "text/html", "ok"); });
- //文件上传
- server.on(
- "/up", HTTP_POST,
- []()
- {
- server.send(200);
- },
- handleFileUpload);
- server.on("/up", HTTP_GET, []()
- {
- String html = "<form method="post" enctype="multipart/form-data">";
- html += "<input type="file" name="name">";
- html += "<input class="button" type="submit" value="Upload">";
- html += "</form>";
- server.send(200, "text/html", html); });
- server.on("/", []()
- {
- server.sendHeader("Location", String("index.html"), true);
- server.send(302, "text/plain", ""); });
- server.on("/tq", HTTP_GET, []() { server.send(200, "text/plain",String(openTemp) +"="+String(check_temp)); });
-
- server.on("/tianqi", HTTP_GET, []() {
- String t_tmp =server.arg("opentemp");
- openTemp=t_tmp.toInt();
-
- if (server.arg("weather")=="true")
- {
- check_temp=true;
- }else{
- check_temp=false;
- }
-
- server.send(200, "text/plain", "ok"); });
- //返回空调设置
- server.on("/state", HTTP_GET, []()
- {
- DynamicJsonDocument root(1024);
- root["mode"] = acState.operation;
- root["fan"] = acState.fan;
- root["temp"] = acState.temperature;
- root["power"] = acState.powerStatus;
- root["Swingmode"] = acState.Swingmode;
- String output;
- serializeJson(root, output);
- server.send(200, "text/plain", output); });
- server.on("/reset", []()
- {
- server.send(200, "text/html", "reset");
- delay(100);
- ESP.restart(); });
- server.serveStatic("/", FILESYSTEM, "/", "max-age=86400");
- server.enableCORS(true);
- server.onNotFound(handleNotFound);
- server.begin();
- ArduinoOTA.setHostname("ESP8266");
- ArduinoOTA.setPassword("12345678");
- ArduinoOTA.begin();
- //天气
- timeClient.begin();
- ticker.attach(1, tickerCount);
- openTemp=27;
- }
- void loop()
- {
- server.handleClient();
- ArduinoOTA.handle();
- if (count >= 1800 && check_temp)
- {
- updateTime();
- delay(1000);
- getTemp();
- count = 0;
- }
- }
复制代码
|
-
手机浏览器
|