初始化提交
@@ -0,0 +1,43 @@
|
||||
# esp8266-AC-control
|
||||
|
||||
This is just a web interface for the IRremoteESP8266 library.
|
||||
|
||||

|
||||
|
||||
|
||||
## 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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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}
|
||||
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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">×</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>
|
||||
@@ -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);
|
||||
}
|
||||