-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathweb.cpp
165 lines (141 loc) · 5.08 KB
/
web.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* Yeelight Smart Switch App for ESP8266
* * Web pages
* (c) DNS 2018-2021
*/
#include "MySystem.h" // System-level definitions
#include "BulbManager.h" // Bulb manager
using namespace ds;
// Initialize page buffer with page header
static void pushHeader(const String& title, bool redirect = false) {
auto &page = System::web_page;
System::pushHTMLHeader(title,
F(
"<style>\n"
" .off { filter: grayscale(100%); }\n"
"</style>\n"),
redirect);
page += F("<h3>");
page += title;
page += F("</h3>\n");
// Navigation
page += F(
"<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td>"
"[ <a href=\"/\">home</a> ] "
"[ <a href=\"/conf\">config</a> ] "
"[ <a href=\"/timers\">timers</a> ] "
"[ <a href=\"/log\">log</a> ]<br/>"
"[ <a href=\"/about\">about</a> ] "
"</td><td align=\"right\" valign=\"top\">"
);
if (System::getTimeSyncStatus() != TIME_SYNC_NONE)
page += System::getTimeStr();
page += F(
"</td></tr></table>"
"<hr/>\n"
);
}
// Append page footer to the buffer
static void pushFooter() {
System::pushHTMLFooter();
}
// Root page. Show status
void handleRoot() {
auto &page = System::web_page;
// Execute command, if any
if (System::web_server.args() > 0) {
for (unsigned int i = 0; i < (unsigned int)System::web_server.args(); i++) {
const String cmd = System::web_server.argName(i);
String reason(F("Web page command \""));
reason += cmd;
reason += F("\" received from ");
reason += System::web_server.client().remoteIP().toString();
if (cmd == "on")
bulb_manager.processEvent(BulbManager::EVENT_ON, reason);
else if (cmd == "off")
bulb_manager.processEvent(BulbManager::EVENT_OFF, reason);
else if (cmd == "flip")
bulb_manager.processEvent(BulbManager::EVENT_FLIP, reason);
else
System::log->printf(TIMED("Invalid command: '%s', ignoring\n"), cmd.c_str());
}
}
pushHeader(F("Yeelight Button"));
// Icon
page += F("<center><span style=\"font-size: 3cm;\"");
if (bulb_manager.isOff())
page += F(" class=\"off\"");
page += F(">\xf0\x9f\x92\xa1"); // UTF-8 'ELECTRIC LIGHT BULB'
page += F("</span><br/>");
//// Newlines are intentional, to facilitate scripting
page += F("\nLights are ");
page += bulb_manager.isOn() ? "ON" : "OFF";
page += F("\n<p>");
page += F("\n<input type='button' name='on' value=' On ' onclick='location.href=\"/?on\"'> ");
page += F("\n<input type='button' name='flip' value='Toggle' onclick='location.href=\"/?flip\"'> ");
page += F("\n<input type='button' name='off' value=' Off ' onclick='location.href=\"/?off\"'>");
page += F("\n</p>\n");
// Table of bulbs
page += F("Linked bulbs:<br/>\n");
bulb_manager.printStatusHTML(page);
page += F("</center>\n");
pushFooter();
System::sendWebPage();
}
// Bulb discovery page
void handleConf() {
auto &page = System::web_page;
pushHeader(F("Yeelight Button Configuration"));
page += F("<p>[ <a href=\"/conf\">rescan</a> ] [ <a href=\"/save\">unlink all</a> ]</p>\n");
page += F("<p><i>Scanning ");
page += System::getNetworkName();
page += F(" for Yeelight devices...</i></p>\n");
page += F("<p><i>Hint: turn all bulbs off, except the desired ones, in order to identify them easily.</i></p>\n");
// Use chunked transfer to show scan in progress
System::web_server.setContentLength(CONTENT_LENGTH_UNKNOWN);
System::sendWebPage();
const auto num_bulbs = bulb_manager.discover();
page = F("<p>Found ");
page += num_bulbs;
page += F(" bulb");
if (num_bulbs != 1)
page += 's';
page += F(". Select bulbs to link from the list below.</p>\n");
page += F("<form action=\"/save\">\n");
bulb_manager.printConfHTML(page);
page += F("<p><input type=\"submit\" value=\"Link\"/></p>\n</form>\n");
pushFooter();
System::web_server.sendContent(page);
System::web_server.sendContent("");
System::web_server.client().stop(); // Terminate chunked transfer
}
// Configuration saving page
void handleSave() {
auto &page = System::web_page;
bulb_manager.save();
const auto nargs = System::web_server.args();
const auto linked = bulb_manager.isLinked();
const auto nabulbs = bulb_manager.getNumActive();
pushHeader(String(F("Yeelight Button Configuration")) + linked || !nargs ? F(" Saved") : F(" Error"), true);
if (nargs) {
if (linked) {
page += F("<p>");
page += nabulbs;
page += F(" bulb");
if (nabulbs > 1)
page += 's';
page += F(" linked</p>");
} else
page += F("<p>Too many bulbs passed</p>");
} else
page += F("<p>Bulbs unlinked</p>");
pushFooter();
System::sendWebPage();
}
// Activate web pages
void registerPages() {
System::web_server.on("/", handleRoot);
System::web_server.on("/conf", handleConf);
System::web_server.on("/save", handleSave);
}
// Install handler
void (*System::registerWebPages)() = registerPages;