feat: 全量同步 254 个常用的 Arduino 扩展库文件

This commit is contained in:
yczpf2019
2026-01-24 16:05:38 +08:00
parent c665ba662b
commit 397b9a23a3
6878 changed files with 2732224 additions and 1 deletions

View File

@@ -0,0 +1,43 @@
# esp8266-AC-control
This is just a web interface for the IRremoteESP8266 library.
![Web Gui Preview](https://github.com/mariusmotea/esp8266-AC-control/raw/master/printscreen.png)
## Instructions:
- Connect IR led to one GPIO pin (recommended pin is GPIO4)
- Edit esp8266-AC-control.ino header marked as "User space". You will need to import the library dedicated for your AC model. Every library has its own commands for AC mode and fan speed that will need to be replace according to commands available in .h file of the library.
- Flash the firmware in ESP board using 1M or 2M of SPIFFS storage.
- Connect the board to your wifi network (look for "AC Remote Control" SSID and follow WiFi Manager wizard)
- Upload web application files in SPIFFS storage using build in web form located at /file-upload path.
## REST API:
Browser console will show the ajax calls to ESP8266 board. Running configuration can be displayed with GET request to /state path, any value can be changed with http PUT request to same path.
Ex:
```
➜ ~ curl 192.168.0.71/state
{"mode":2,"fan":0,"temp":27,"power":true}%
➜ ~ curl -X PUT -d '{"temp":22}' 192.168.0.71/state
{"temp":22}%
➜ ~ curl 192.168.0.71/state
{"mode":2,"fan":0,"temp":22,"power":true}%
```
## DEBUG:
Use mobile phone camera to see if the led is sending any IR signals when buttons are pressed. This will show if the circuit was properly made and the selected GPIO pin is the correct one.
## Credits:
Interface: https://github.com/ael-code/daikin-control

View File

@@ -0,0 +1,300 @@
/* Copyright 2019 Motea Marius
This example code will create a webserver that will provide basic control to AC units using the web application
build with javascript/css. User config zone need to be updated if a different class than Collix need to be used.
Javasctipt file may also require minor changes as in current version it will not allow to set fan speed if Auto mode
is selected (required for Coolix).
*/
#include <FS.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 <SPIFFS.h>
#include <Update.h>
#endif // ESP32
#include <WiFiUdp.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
//// ###### User configuration space for AC library classes ##########
#include <ir_Coolix.h> // replace library based on your AC unit model, check https://github.com/crankyoldgit/IRremoteESP8266
#define AUTO_MODE kCoolixAuto
#define COOL_MODE kCoolixCool
#define DRY_MODE kCoolixDry
#define HEAT_MODE kCoolixHeat
#define FAN_MODE kCoolixFan
#define FAN_AUTO kCoolixFanAuto
#define FAN_MIN kCoolixFanMin
#define FAN_MED kCoolixFanMed
#define FAN_HI kCoolixFanMax
// ESP8266 GPIO pin to use for IR blaster.
const uint16_t kIrLed = 4;
// Library initialization, change it according to the imported library file.
IRCoolixAC ac(kIrLed);
/// ##### End user configuration ######
struct state {
uint8_t temperature = 22, fan = 0, operation = 0;
bool powerStatus;
};
File fsUploadFile;
// core
state acState;
// settings
char deviceName[] = "AC Remote Control";
#if defined(ESP8266)
ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdateServer;
#endif // ESP8266
#if defined(ESP32)
WebServer server(80);
#endif // ESP32
bool handleFileRead(String path) {
// send the right file to the client (if it exists)
// Serial.println("handleFileRead: " + path);
if (path.endsWith("/")) path += "index.html";
// If a folder is requested, send the index file
String contentType = getContentType(path);
// Get the MIME type
String pathWithGz = path + ".gz";
if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) {
// If the file exists, either as a compressed archive, or normal
if (SPIFFS.exists(pathWithGz)) // If there's a compressed version available
path += ".gz"; // Use the compressed verion
File file = SPIFFS.open(path, "r");
// Open the file
server.streamFile(file, contentType);
// Send it to the client
file.close();
// Close the file again
// Serial.println(String("\tSent file: ") + path);
return true;
}
// Serial.println(String("\tFile Not Found: ") + path);
// If the file doesn't exist, return false
return false;
}
String getContentType(String filename) {
// convert the file extension to the MIME type
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() { // upload a new file to the SPIFFS
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
String filename = upload.filename;
if (!filename.startsWith("/")) filename = "/" + filename;
// Serial.print("handleFileUpload Name: "); //Serial.println(filename);
fsUploadFile = SPIFFS.open(filename, "w");
// Open the file for writing in SPIFFS (create if it doesn't exist)
filename = String();
} else if (upload.status == UPLOAD_FILE_WRITE) {
if (fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize);
// Write the received bytes to the file
} else if (upload.status == UPLOAD_FILE_END) {
if (fsUploadFile) {
// If the file was successfully created
fsUploadFile.close();
// Close the file again
// Serial.print("handleFileUpload Size: ");
// Serial.println(upload.totalSize);
server.sendHeader("Location", "/success.html");
// Redirect the client to the success page
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 FS...");
if (!SPIFFS.begin()) {
// Serial.println("Failed to mount file system");
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_PUT, []() {
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"];
}
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);
}
}
} else {
ac.off();
}
ac.send();
}
});
server.on("/file-upload", HTTP_POST,
// if the client posts to the upload page
[]() {
// Send status 200 (OK) to tell the client we are ready to receive
server.send(200);
},
handleFileUpload); // Receive and save the file
server.on("/file-upload", HTTP_GET, []() {
// if the client requests the upload page
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("ui.html"), true);
server.send(302, "text/plain", "");
});
server.on("/state", HTTP_GET, []() {
DynamicJsonDocument root(1024);
root["mode"] = acState.operation;
root["fan"] = acState.fan;
root["temp"] = acState.temperature;
root["power"] = acState.powerStatus;
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("/", SPIFFS, "/", "max-age=86400");
server.onNotFound(handleNotFound);
server.begin();
}
void loop() {
server.handleClient();
}

View File

@@ -0,0 +1,37 @@
[platformio]
src_dir = .
[env]
lib_extra_dirs = ../../
lib_ldf_mode = deep+
lib_ignore = examples
framework = arduino
monitor_speed = 115200
build_flags = ; -D_IR_LOCALE_=en-AU
[common]
lib_deps_builtin =
lib_deps_external =
ArduinoJson@>=6.0
[common_esp8266]
lib_deps_external =
${common.lib_deps_builtin}
${common.lib_deps_external}
WifiManager@>=0.14
[common_esp32]
lib_deps_external =
${common.lib_deps_builtin}
${common.lib_deps_external}
https://github.com/tzapu/WiFiManager.git#development
[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
lib_deps = ${common_esp8266.lib_deps_external}
[env:esp32dev]
platform = espressif32
board = esp32dev
lib_deps = ${common_esp32.lib_deps_external}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="236.64082"
height="86.640839"
rx="15.946075"
ry="15.666504"
x="6.6795802"
y="959.03809"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:0;stroke:#000000;stroke-width:13.35916042;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="236.64082"
height="86.640839"
rx="15.946075"
ry="15.666504"
x="6.6795802"
y="959.03809"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:1;stroke:#000000;stroke-width:13.35916042;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="230.92926"
height="180.92929"
rx="22.392242"
ry="22.274536"
x="9.5353565"
y="861.89758"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:0;stroke:#000000;stroke-width:19.07071304;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="230.92926"
height="180.92929"
rx="22.392242"
ry="22.274536"
x="9.5353565"
y="861.89758"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:1;stroke:#000000;stroke-width:19.07071304;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="226.6387"
height="276.63873"
rx="36.69751"
ry="40.173462"
x="11.680637"
y="764.04285"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:0;stroke:#000000;stroke-width:23.36127472;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="226.6387"
height="276.63873"
rx="36.69751"
ry="40.173462"
x="11.680637"
y="764.04285"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:1;stroke:#000000;stroke-width:23.36127472;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="223.08398"
height="373.08401"
rx="40.059196"
ry="46.087463"
x="13.458"
y="665.82019"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:0;stroke:#000000;stroke-width:26.91600037;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="250"
height="500"
id="svg2">
<defs
id="defs4">
<linearGradient
id="linearGradient4457">
<stop
id="stop4459"
style="stop-color:#0000ff;stop-opacity:1"
offset="0" />
</linearGradient>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-552.36218)"
id="layer1">
<rect
width="223.08398"
height="373.08401"
rx="40.059196"
ry="46.087463"
x="13.458"
y="665.82019"
id="rect2995"
style="opacity:0.87999998;fill:#46b8da;fill-opacity:1;stroke:#000000;stroke-width:26.91600037;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:35.90000153;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Home Temperature</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='shortcut icon' type='image/x-icon' href='favicon.ico' />
<style type="text/css">
body { padding-top: 70px; }
</style>
<!-- Font Awsome -->
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
</head>
<!--page content-->
<body>
<div class='container'>
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-brand">
<p>AC Control</p>
</div>
<p class="navbar-text navbar-right sr-only" id="spinner"><i class="fa fa-circle-o-notch fa-spin fa-lg"></i></p>
</div>
</nav>
<div class="alert alert-danger sr-only" id="alert">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<p></p>
</div>
<div class="container-fluid">
<div class="row">
<!-- ON/OFF -->
<div class="col-sm-offset-10 col-sm-2 pull-right">
<a id="power-btn" class="btn btn-default" onclick='power_onclick();'><i class="fa fa-power-off" style="font-size:1.6em;color:black;"></i><b style="font-size:1.5em;" id="power"> OFF</b></a>
</div>
</div>
<br>
<div class="row">
<div class="col-md-4 col-sm-6">
<!-- Mode -->
<h4>Mode</h4>
<div class="btn-group">
<a class="btn btn-default mode-btn" id="mode_cooling" onclick='mode_onclick(1);'><i class="fa fa-asterisk fa-2x"></i></a>
<a class="btn btn-default mode-btn" id="mode_dehum" onclick='mode_onclick(2);'><i class="fa fa-tint fa-2x"></i></a>
<a class="btn btn-default mode-btn" id="mode_heating" onclick='mode_onclick(3);'><i class="fa fa-sun-o fa-2x"></i></a>
<a class="btn btn-default mode-btn" id="mode_fan" onclick='mode_onclick(4);'><i class="fa fa-retweet fa-2x"></i></a>
<a class="btn btn-default mode-btn" id="mode_auto" onclick='mode_onclick(0);'><i class="fa fa-font fa-2x"></i></a>
</div>
</div>
<div class="col-md-4 col-sm-6">
<!-- Fan -->
<h4>Fan</h4>
<div class="btn-group">
<a class="btn btn-default fan-btn" id="fan_auto" onclick='fan_onclick("0");'><i class="fa fa-font fa-2x"></i></a>
<a class="btn btn-default" onclick='fan_onclick(1);'><img src="level_1_off.svg" height="29px" id="fan_lvl_1"></a>
<a class="btn btn-default" onclick='fan_onclick(2);'><img src="level_2_off.svg" height="29px" id="fan_lvl_2"></a>
<a class="btn btn-default" onclick='fan_onclick(3);'><img src="level_3_off.svg" height="29px" id="fan_lvl_3"></a>
</div>
</div>
</div>
<br>
<br>
<div class="row">
<div class="col-md-4 col-sm-6" id="target_temp_col">
<!--Target temperature-->
<h4>Target temperature</h4>
<div class="btn-group" >
<a class="btn btn-default" style="font-size:2.2em;padding-top:12px;padding-bottom:12px;"><b id="target_temp"> ~ C</b></a>
</div>
<div class="btn-group-vertical">
<a class="btn btn-default wing-btn" id="target_temp_up" onclick='temp_onclick(1);' style="font-size:1.7em;padding-top:0px;padding-bottom:0px;"><i class="fa fa-chevron-up"></i></a>
<a class="btn btn-default wing-btn" id="target_temp_down" onclick='temp_onclick(-1);' style="font-size:1.7em;padding-top:0px;padding-bottom:0px;"><i class="fa fa-chevron-down"></i></a>
</div>
</div>
</div>
</div>
</div>
<br>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="ui.js"></script>
</body>
</html>

View File

@@ -0,0 +1,132 @@
var state = {}
function updateStatus() {
$.ajax({
type: 'GET',
url: "state",
dataType: "json",
data: [{
name: "light",
value: "1"
}, ],
success: function(data) {
if (!data) {
return;
}
state = data;
if (state["power"] === true) {
$("#power").text(" ON");
$("#power-btn").addClass("btn-info");
$("#power-btn").removeClass("btn-default");
} else {
$("#power").text(" OFF");
$("#power-btn").addClass("btn-default");
$("#power-btn").removeClass("btn-info");
}
$("#target_temp").text(state["temp"] + " C");
setModeColor(state["mode"]);
setFanColor(state["fan"]);
},
error: function() {
console.log('error getting state');
},
timeout: 1000
});
}
updateStatus();
function postData(t) {
var e = new XMLHttpRequest;
e.timeout = 2000;
e.open("PUT", "state", !0);
e.setRequestHeader("Content-Type", "application/json");
console.log(JSON.stringify(t)), e.send(JSON.stringify(t));
}
function mode_onclick(mode) {
state["mode"] = mode;
setModeColor(mode);
postData(state);
}
function setModeColor(mode) {
$(".mode-btn").addClass("btn-default");
$(".mode-btn").removeClass("btn-info");
if (mode === 0) {
$("#mode_auto").removeClass("btn-default");
$("#mode_auto").addClass("btn-info");
setFanColor(0);
state["fan"] = 0;
} else if (mode === 1) {
$("#mode_cooling").removeClass("btn-default");
$("#mode_cooling").addClass("btn-info");
} else if (mode === 2) {
$("#mode_dehum").removeClass("btn-default");
$("#mode_dehum").addClass("btn-info");
} else if (mode === 3) {
$("#mode_heating").removeClass("btn-default");
$("#mode_heating").addClass("btn-info");
} else if (mode === 4) {
$("#mode_fan").removeClass("btn-default");
$("#mode_fan").addClass("btn-info");
}
}
function setFanColor(fan) {
if (fan == 0) {
$("#fan_auto").removeClass("btn-default");
$("#fan_auto").addClass("btn-info");
} else {
$("#fan_auto").removeClass("btn-info");
$("#fan_auto").addClass("btn-default");
}
for (var i = 1; i <= 3; ++i) {
if (i <= fan) {
$("#fan_lvl_" + i).attr("src", "level_" + i + "_on.svg");
} else {
$("#fan_lvl_" + i).attr("src", "level_" + i + "_off.svg");
}
}
}
function fan_onclick(fan) {
if (state["mode"] !== 0) {
state["fan"] = fan;
setFanColor(fan);
postData(state);
}
}
function power_onclick(power) {
if (state["power"]) {
state["power"] = false;
$("#power").text(" OFF");
$("#power-btn").removeClass("btn-info");
$("#power-btn").addClass("btn-default");
} else {
state["power"] = true;
$("#power").text(" ON");
$("#power-btn").addClass("btn-info");
$("#power-btn").removeClass("btn-default");
}
postData(state);
}
function temp_onclick(temp) {
state["temp"] += temp;
if (state["temp"] < 17) {
state["temp"] = 17;
}
if (state["temp"] > 30) {
state["temp"] = 30;
}
$("#target_temp").text(state["temp"] + " C");
postData(state);
}