ESPHome 2025.5.0
Loading...
Searching...
No Matches
web_server_v1.cpp
Go to the documentation of this file.
1#include "web_server.h"
3
4#if USE_WEBSERVER_VERSION == 1
5
6namespace esphome {
7namespace web_server {
8
9void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action,
10 const std::function<void(AsyncResponseStream &stream, EntityBase *obj)> &action_func = nullptr) {
11 stream->print("<tr class=\"");
12 stream->print(klass.c_str());
13 if (obj->is_internal())
14 stream->print(" internal");
15 stream->print("\" id=\"");
16 stream->print(klass.c_str());
17 stream->print("-");
18 stream->print(obj->get_object_id().c_str());
19 stream->print("\"><td>");
20 stream->print(obj->get_name().c_str());
21 stream->print("</td><td></td><td>");
22 stream->print(action.c_str());
23 if (action_func) {
24 action_func(*stream, obj);
25 }
26 stream->print("</td>");
27 stream->print("</tr>");
28}
29
30void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; }
31
32void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; }
33
34void WebServer::handle_index_request(AsyncWebServerRequest *request) {
35 AsyncResponseStream *stream = request->beginResponseStream("text/html");
36 const std::string &title = App.get_name();
37 stream->print(F("<!DOCTYPE html><html lang=\"en\"><head><meta charset=UTF-8><meta "
38 "name=viewport content=\"width=device-width, initial-scale=1,user-scalable=no\"><title>"));
39 stream->print(title.c_str());
40 stream->print(F("</title>"));
41#ifdef USE_WEBSERVER_CSS_INCLUDE
42 stream->print(F("<link rel=\"stylesheet\" href=\"/0.css\">"));
43#endif
44 if (strlen(this->css_url_) > 0) {
45 stream->print(F(R"(<link rel="stylesheet" href=")"));
46 stream->print(this->css_url_);
47 stream->print(F("\">"));
48 }
49 stream->print(F("</head><body>"));
50 stream->print(F("<article class=\"markdown-body\"><h1>"));
51 stream->print(title.c_str());
52 stream->print(F("</h1>"));
53 stream->print(F("<h2>States</h2><table id=\"states\"><thead><tr><th>Name<th>State<th>Actions<tbody>"));
54
55#ifdef USE_SENSOR
56 for (auto *obj : App.get_sensors()) {
57 if (this->include_internal_ || !obj->is_internal())
58 write_row(stream, obj, "sensor", "");
59 }
60#endif
61
62#ifdef USE_SWITCH
63 for (auto *obj : App.get_switches()) {
64 if (this->include_internal_ || !obj->is_internal())
65 write_row(stream, obj, "switch", "<button>Toggle</button>");
66 }
67#endif
68
69#ifdef USE_BUTTON
70 for (auto *obj : App.get_buttons())
71 write_row(stream, obj, "button", "<button>Press</button>");
72#endif
73
74#ifdef USE_BINARY_SENSOR
75 for (auto *obj : App.get_binary_sensors()) {
76 if (this->include_internal_ || !obj->is_internal())
77 write_row(stream, obj, "binary_sensor", "");
78 }
79#endif
80
81#ifdef USE_FAN
82 for (auto *obj : App.get_fans()) {
83 if (this->include_internal_ || !obj->is_internal())
84 write_row(stream, obj, "fan", "<button>Toggle</button>");
85 }
86#endif
87
88#ifdef USE_LIGHT
89 for (auto *obj : App.get_lights()) {
90 if (this->include_internal_ || !obj->is_internal())
91 write_row(stream, obj, "light", "<button>Toggle</button>");
92 }
93#endif
94
95#ifdef USE_TEXT_SENSOR
96 for (auto *obj : App.get_text_sensors()) {
97 if (this->include_internal_ || !obj->is_internal())
98 write_row(stream, obj, "text_sensor", "");
99 }
100#endif
101
102#ifdef USE_COVER
103 for (auto *obj : App.get_covers()) {
104 if (this->include_internal_ || !obj->is_internal())
105 write_row(stream, obj, "cover", "<button>Open</button><button>Close</button>");
106 }
107#endif
108
109#ifdef USE_NUMBER
110 for (auto *obj : App.get_numbers()) {
111 if (this->include_internal_ || !obj->is_internal()) {
112 write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) {
113 number::Number *number = (number::Number *) obj;
114 stream.print(R"(<input type="number" min=")");
115 stream.print(number->traits.get_min_value());
116 stream.print(R"(" max=")");
117 stream.print(number->traits.get_max_value());
118 stream.print(R"(" step=")");
119 stream.print(number->traits.get_step());
120 stream.print(R"(" value=")");
121 stream.print(number->state);
122 stream.print(R"("/>)");
123 });
124 }
125 }
126#endif
127
128#ifdef USE_TEXT
129 for (auto *obj : App.get_texts()) {
130 if (this->include_internal_ || !obj->is_internal()) {
131 write_row(stream, obj, "text", "", [](AsyncResponseStream &stream, EntityBase *obj) {
132 text::Text *text = (text::Text *) obj;
133 auto mode = (int) text->traits.get_mode();
134 stream.print(R"(<input type=")");
135 if (mode == 2) {
136 stream.print(R"(password)");
137 } else { // default
138 stream.print(R"(text)");
139 }
140 stream.print(R"(" minlength=")");
141 stream.print(text->traits.get_min_length());
142 stream.print(R"(" maxlength=")");
143 stream.print(text->traits.get_max_length());
144 stream.print(R"(" pattern=")");
145 stream.print(text->traits.get_pattern().c_str());
146 stream.print(R"(" value=")");
147 stream.print(text->state.c_str());
148 stream.print(R"("/>)");
149 });
150 }
151 }
152#endif
153
154#ifdef USE_SELECT
155 for (auto *obj : App.get_selects()) {
156 if (this->include_internal_ || !obj->is_internal()) {
157 write_row(stream, obj, "select", "", [](AsyncResponseStream &stream, EntityBase *obj) {
158 select::Select *select = (select::Select *) obj;
159 stream.print("<select>");
160 stream.print("<option></option>");
161 for (auto const &option : select->traits.get_options()) {
162 stream.print("<option>");
163 stream.print(option.c_str());
164 stream.print("</option>");
165 }
166 stream.print("</select>");
167 });
168 }
169 }
170#endif
171
172#ifdef USE_LOCK
173 for (auto *obj : App.get_locks()) {
174 if (this->include_internal_ || !obj->is_internal()) {
175 write_row(stream, obj, "lock", "", [](AsyncResponseStream &stream, EntityBase *obj) {
176 lock::Lock *lock = (lock::Lock *) obj;
177 stream.print("<button>Lock</button><button>Unlock</button>");
178 if (lock->traits.get_supports_open()) {
179 stream.print("<button>Open</button>");
180 }
181 });
182 }
183 }
184#endif
185
186#ifdef USE_CLIMATE
187 for (auto *obj : App.get_climates()) {
188 if (this->include_internal_ || !obj->is_internal())
189 write_row(stream, obj, "climate", "");
190 }
191#endif
192
193 stream->print(F("</tbody></table><p>See <a href=\"https://esphome.io/web-api/index.html\">ESPHome Web API</a> for "
194 "REST API documentation.</p>"));
195 if (this->allow_ota_) {
196 stream->print(
197 F("<h2>OTA Update</h2><form method=\"POST\" action=\"/update\" enctype=\"multipart/form-data\"><input "
198 "type=\"file\" name=\"update\"><input type=\"submit\" value=\"Update\"></form>"));
199 }
200 stream->print(F("<h2>Debug Log</h2><pre id=\"log\"></pre>"));
201#ifdef USE_WEBSERVER_JS_INCLUDE
202 if (this->js_include_ != nullptr) {
203 stream->print(F("<script type=\"module\" src=\"/0.js\"></script>"));
204 }
205#endif
206 if (strlen(this->js_url_) > 0) {
207 stream->print(F("<script src=\""));
208 stream->print(this->js_url_);
209 stream->print(F("\"></script>"));
210 }
211 stream->print(F("</article></body></html>"));
212 request->send(stream);
213}
214
215} // namespace web_server
216} // namespace esphome
217#endif
BedjetMode mode
BedJet operating mode.
const std::vector< button::Button * > & get_buttons()
const std::vector< fan::Fan * > & get_fans()
const std::vector< switch_::Switch * > & get_switches()
const std::vector< sensor::Sensor * > & get_sensors()
const std::vector< text_sensor::TextSensor * > & get_text_sensors()
const std::vector< lock::Lock * > & get_locks()
const std::vector< select::Select * > & get_selects()
const std::vector< text::Text * > & get_texts()
const std::vector< climate::Climate * > & get_climates()
const std::vector< light::LightState * > & get_lights()
const std::string & get_name() const
Get the name of this Application set by pre_setup().
const std::vector< cover::Cover * > & get_covers()
const std::vector< binary_sensor::BinarySensor * > & get_binary_sensors()
const std::vector< number::Number * > & get_numbers()
void set_css_url(const char *css_url)
Set the URL to the CSS <link> that's sent to each client.
void set_js_url(const char *js_url)
Set the URL to the script that's embedded in the index page.
void handle_index_request(AsyncWebServerRequest *request)
Handle an index request under '/'.
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
Application App
Global storage of Application pointer - only one Application can exist.