ESPHome  2024.9.0
web_server_v1.cpp
Go to the documentation of this file.
1 #include "web_server.h"
3 
4 #if USE_WEBSERVER_VERSION == 1
5 
6 namespace esphome {
7 namespace web_server {
8 
9 void 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 
30 void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; }
31 
32 void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; }
33 
34 void 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
TextMode get_mode() const
Definition: text_traits.h:29
std::string state
Definition: text.h:26
const std::vector< climate::Climate * > & get_climates()
Definition: application.h:327
TextTraits traits
Definition: text.h:27
void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action, const std::function< void(AsyncResponseStream &stream, EntityBase *obj)> &action_func=nullptr)
SelectTraits traits
Definition: select.h:34
const std::vector< fan::Fan * > & get_fans()
Definition: application.h:297
int get_max_length() const
Definition: text_traits.h:21
Base-class for all text inputs.
Definition: text.h:24
std::string get_object_id() const
Definition: entity_base.cpp:43
LockTraits traits
Definition: lock.h:124
const std::vector< lock::Lock * > & get_locks()
Definition: application.h:397
const std::vector< button::Button * > & get_buttons()
Definition: application.h:267
std::vector< std::string > get_options() const
const std::vector< switch_::Switch * > & get_switches()
Definition: application.h:257
Base-class for all numbers.
Definition: number.h:39
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:181
bool is_internal() const
Definition: entity_base.cpp:22
const std::vector< text_sensor::TextSensor * > & get_text_sensors()
Definition: application.h:287
const std::vector< sensor::Sensor * > & get_sensors()
Definition: application.h:277
Application App
Global storage of Application pointer - only one Application can exist.
const std::vector< binary_sensor::BinarySensor * > & get_binary_sensors()
Definition: application.h:247
const std::string & get_name() const
Get the name of this Application set by pre_setup().
Definition: application.h:202
const std::vector< text::Text * > & get_texts()
Definition: application.h:377
void handle_index_request(AsyncWebServerRequest *request)
Handle an index request under &#39;/&#39;.
Definition: web_server.cpp:151
NumberTraits traits
Definition: number.h:49
const std::vector< cover::Cover * > & get_covers()
Definition: application.h:307
constexpr const char * c_str() const
Definition: string_ref.h:68
void set_js_url(const char *js_url)
Set the URL to the script that&#39;s embedded in the index page.
void set_css_url(const char *css_url)
Set the URL to the CSS <link> that&#39;s sent to each client.
const std::vector< light::LightState * > & get_lights()
Definition: application.h:317
Base-class for all selects.
Definition: select.h:31
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
int get_min_length() const
Definition: text_traits.h:19
const std::vector< select::Select * > & get_selects()
Definition: application.h:387
const std::vector< number::Number * > & get_numbers()
Definition: application.h:337
bool get_supports_open() const
Definition: lock.h:40
std::string get_pattern() const
Definition: text_traits.h:25
const StringRef & get_name() const
Definition: entity_base.cpp:10
Base class for all locks.
Definition: lock.h:103