12#include "StreamString.h"
29#ifdef USE_WEBSERVER_LOCAL
30#if USE_WEBSERVER_VERSION == 2
32#elif USE_WEBSERVER_VERSION == 3
40static const char *
const TAG =
"web_server";
42#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
43static const char *
const HEADER_PNA_NAME =
"Private-Network-Access-Name";
44static const char *
const HEADER_PNA_ID =
"Private-Network-Access-ID";
45static const char *
const HEADER_CORS_REQ_PNA =
"Access-Control-Request-Private-Network";
46static const char *
const HEADER_CORS_ALLOW_PNA =
"Access-Control-Allow-Private-Network";
52 size_t domain_end = url.find(
'/', 1);
53 if (domain_end == std::string::npos)
55 match.
domain = url.substr(1, domain_end - 1);
60 if (url.length() == domain_end - 1)
62 size_t id_begin = domain_end + 1;
63 size_t id_end = url.find(
'/', id_begin);
65 if (id_end == std::string::npos) {
66 match.
id = url.substr(id_begin, url.length() - id_begin);
69 match.
id = url.substr(id_begin, id_end - id_begin);
70 size_t method_begin = id_end + 1;
71 match.
method = url.substr(method_begin, url.length() - method_begin);
78 DeferredEvent item(source, message_generator);
80 auto iter = std::find_if(this->
deferred_queue_.begin(), this->deferred_queue_.end(),
81 [&item](
const DeferredEvent &test) ->
bool { return test == item; });
93 std::string message = de.message_generator_(
web_server_, de.source_);
94 if (this->try_send(message.c_str(),
"state")) {
116 if (source ==
nullptr)
118 if (event_type ==
nullptr)
120 if (message_generator ==
nullptr)
123 if (0 != strcmp(event_type,
"state_detail_all") && 0 != strcmp(event_type,
"state")) {
124 ESP_LOGE(TAG,
"Can't defer non-state event");
133 std::string message = message_generator(
web_server_, source);
134 if (!this->try_send(message.c_str(),
"state")) {
142 uint32_t reconnect) {
143 this->send(message, event,
id, reconnect);
160 uint32_t reconnect) {
170 es->onConnect([
this, ws, es](AsyncEventSourceClient *client) {
174 es->onDisconnect([
this, ws](AsyncEventSource *source, AsyncEventSourceClient *client) {
178 es->handleRequest(request);
189 root[
"name"] = group.second.name;
190 root[
"sorting_weight"] = group.second.weight;
209 this->remove(source);
220#ifdef USE_WEBSERVER_CSS_INCLUDE
223#ifdef USE_WEBSERVER_JS_INCLUDE
238 ESP_LOGCONFIG(TAG,
"Running setup");
246 [
this](
int level,
const char *tag,
const char *message) {
267 std::function<void()> fn;
292#ifdef USE_WEBSERVER_LOCAL
294 AsyncWebServerResponse *response = request->beginResponse_P(200,
"text/html", INDEX_GZ,
sizeof(INDEX_GZ));
295 response->addHeader(
"Content-Encoding",
"gzip");
296 request->send(response);
298#elif USE_WEBSERVER_VERSION >= 2
300 AsyncWebServerResponse *response =
303 request->send(response);
307#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
309 AsyncWebServerResponse *response = request->beginResponse(200,
"");
310 response->addHeader(HEADER_CORS_ALLOW_PNA,
"true");
311 response->addHeader(HEADER_PNA_NAME,
App.
get_name().c_str());
313 response->addHeader(HEADER_PNA_ID, mac.c_str());
314 request->send(response);
318#ifdef USE_WEBSERVER_CSS_INCLUDE
320 AsyncWebServerResponse *response =
322 response->addHeader(
"Content-Encoding",
"gzip");
323 request->send(response);
327#ifdef USE_WEBSERVER_JS_INCLUDE
329 AsyncWebServerResponse *response =
331 response->addHeader(
"Content-Encoding",
"gzip");
332 request->send(response);
336#define set_json_id(root, obj, sensor, start_config) \
337 (root)["id"] = sensor; \
338 if (((start_config) == DETAIL_ALL)) { \
339 (root)["name"] = (obj)->get_name(); \
340 (root)["icon"] = (obj)->get_icon(); \
341 (root)["entity_category"] = (obj)->get_entity_category(); \
342 if ((obj)->is_disabled_by_default()) \
343 (root)["is_disabled_by_default"] = (obj)->is_disabled_by_default(); \
346#define set_json_value(root, obj, sensor, value, start_config) \
347 set_json_id((root), (obj), sensor, start_config); \
348 (root)["value"] = value;
350#define set_json_icon_state_value(root, obj, sensor, state, value, start_config) \
351 set_json_value(root, obj, sensor, value, start_config); \
352 (root)["state"] = state;
362 if (obj->get_object_id() != match.
id)
364 if (request->method() == HTTP_GET && match.
method.empty()) {
366 auto *param = request->getParam(
"detail");
367 if (param && param->value() ==
"all") {
370 std::string data = this->
sensor_json(obj, obj->state, detail);
371 request->send(200,
"application/json", data.c_str());
386 if (std::isnan(value)) {
393 set_json_icon_state_value(root, obj,
"sensor-" + obj->
get_object_id(),
state, value, start_config);
397 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
408#ifdef USE_TEXT_SENSOR
416 if (obj->get_object_id() != match.
id)
418 if (request->method() == HTTP_GET && match.
method.empty()) {
420 auto *param = request->getParam(
"detail");
421 if (param && param->value() ==
"all") {
425 request->send(200,
"application/json", data.c_str());
442 set_json_icon_state_value(root, obj,
"text_sensor-" + obj->
get_object_id(), value, value, start_config);
446 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
463 if (obj->get_object_id() != match.
id)
466 if (request->method() == HTTP_GET && match.
method.empty()) {
468 auto *param = request->getParam(
"detail");
469 if (param && param->value() ==
"all") {
472 std::string data = this->
switch_json(obj, obj->state, detail);
473 request->send(200,
"application/json", data.c_str());
474 }
else if (match.
method ==
"toggle") {
475 this->
schedule_([obj]() { obj->toggle(); });
477 }
else if (match.
method ==
"turn_on") {
478 this->
schedule_([obj]() { obj->turn_on(); });
480 }
else if (match.
method ==
"turn_off") {
481 this->
schedule_([obj]() { obj->turn_off(); });
498 set_json_icon_state_value(root, obj,
"switch-" + obj->
get_object_id(), value ?
"ON" :
"OFF", value, start_config);
503 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
515 if (obj->get_object_id() != match.
id)
517 if (request->method() == HTTP_GET && match.
method.empty()) {
519 auto *param = request->getParam(
"detail");
520 if (param && param->value() ==
"all") {
524 request->send(200,
"application/json", data.c_str());
525 }
else if (match.
method ==
"press") {
526 this->
schedule_([obj]() { obj->press(); });
544 set_json_id(root, obj,
"button-" + obj->
get_object_id(), start_config);
548 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
557#ifdef USE_BINARY_SENSOR
565 if (obj->get_object_id() != match.
id)
567 if (request->method() == HTTP_GET && match.
method.empty()) {
569 auto *param = request->getParam(
"detail");
570 if (param && param->value() ==
"all") {
574 request->send(200,
"application/json", data.c_str());
590 set_json_icon_state_value(root, obj,
"binary_sensor-" + obj->
get_object_id(), value ?
"ON" :
"OFF", value,
595 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
612 if (obj->get_object_id() != match.
id)
615 if (request->method() == HTTP_GET && match.
method.empty()) {
617 auto *param = request->getParam(
"detail");
618 if (param && param->value() ==
"all") {
621 std::string data = this->
fan_json(obj, detail);
622 request->send(200,
"application/json", data.c_str());
623 }
else if (match.
method ==
"toggle") {
624 this->
schedule_([obj]() { obj->toggle().perform(); });
626 }
else if (match.
method ==
"turn_on" || match.
method ==
"turn_off") {
627 auto call = match.
method ==
"turn_on" ? obj->turn_on() : obj->turn_off();
629 if (request->hasParam(
"speed_level")) {
630 auto speed_level = request->getParam(
"speed_level")->value();
632 if (!
val.has_value()) {
633 ESP_LOGW(TAG,
"Can't convert '%s' to number!", speed_level.c_str());
638 if (request->hasParam(
"oscillation")) {
639 auto speed = request->getParam(
"oscillation")->value();
643 call.set_oscillating(
true);
646 call.set_oscillating(
false);
649 call.set_oscillating(!obj->oscillating);
676 if (traits.supports_speed()) {
677 root[
"speed_level"] = obj->
speed;
678 root[
"speed_count"] = traits.supported_speed_count();
685 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
702 if (obj->get_object_id() != match.
id)
705 if (request->method() == HTTP_GET && match.
method.empty()) {
707 auto *param = request->getParam(
"detail");
708 if (param && param->value() ==
"all") {
711 std::string data = this->
light_json(obj, detail);
712 request->send(200,
"application/json", data.c_str());
713 }
else if (match.
method ==
"toggle") {
714 this->
schedule_([obj]() { obj->toggle().perform(); });
716 }
else if (match.
method ==
"turn_on") {
717 auto call = obj->turn_on();
718 if (request->hasParam(
"brightness")) {
720 if (brightness.has_value()) {
721 call.set_brightness(*brightness / 255.0f);
724 if (request->hasParam(
"r")) {
727 call.set_red(*r / 255.0f);
730 if (request->hasParam(
"g")) {
733 call.set_green(*g / 255.0f);
736 if (request->hasParam(
"b")) {
739 call.set_blue(*b / 255.0f);
742 if (request->hasParam(
"white_value")) {
744 if (white_value.has_value()) {
745 call.set_white(*white_value / 255.0f);
748 if (request->hasParam(
"color_temp")) {
750 if (color_temp.has_value()) {
751 call.set_color_temperature(*color_temp);
754 if (request->hasParam(
"flash")) {
756 if (flash.has_value()) {
757 call.set_flash_length(*flash * 1000);
760 if (request->hasParam(
"transition")) {
762 if (transition.has_value()) {
763 call.set_transition_length(*transition * 1000);
766 if (request->hasParam(
"effect")) {
767 const char *effect = request->getParam(
"effect")->value().c_str();
768 call.set_effect(effect);
773 }
else if (match.
method ==
"turn_off") {
774 auto call = obj->turn_off();
775 if (request->hasParam(
"transition")) {
777 if (transition.has_value()) {
778 call.set_transition_length(*transition * 1000);
798 set_json_id(root, obj,
"light-" + obj->
get_object_id(), start_config);
803 JsonArray opt = root.createNestedArray(
"effects");
806 opt.add(option->get_name());
810 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
827 if (obj->get_object_id() != match.
id)
830 if (request->method() == HTTP_GET && match.
method.empty()) {
832 auto *param = request->getParam(
"detail");
833 if (param && param->value() ==
"all") {
836 std::string data = this->
cover_json(obj, detail);
837 request->send(200,
"application/json", data.c_str());
841 auto call = obj->make_call();
842 if (match.
method ==
"open") {
843 call.set_command_open();
844 }
else if (match.
method ==
"close") {
845 call.set_command_close();
846 }
else if (match.
method ==
"stop") {
847 call.set_command_stop();
848 }
else if (match.
method ==
"toggle") {
849 call.set_command_toggle();
850 }
else if (match.
method !=
"set") {
855 auto traits = obj->get_traits();
856 if ((request->hasParam(
"position") && !traits.get_supports_position()) ||
857 (request->hasParam(
"tilt") && !traits.get_supports_tilt())) {
862 if (request->hasParam(
"position")) {
868 if (request->hasParam(
"tilt")) {
870 if (
tilt.has_value()) {
896 root[
"tilt"] = obj->
tilt;
900 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
917 if (obj->get_object_id() != match.
id)
920 if (request->method() == HTTP_GET && match.
method.empty()) {
922 auto *param = request->getParam(
"detail");
923 if (param && param->value() ==
"all") {
926 std::string data = this->
number_json(obj, obj->state, detail);
927 request->send(200,
"application/json", data.c_str());
930 if (match.
method !=
"set") {
935 auto call = obj->make_call();
936 if (request->hasParam(
"value")) {
938 if (value.has_value())
939 call.set_value(*value);
957 set_json_id(root, obj,
"number-" + obj->
get_object_id(), start_config);
970 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
975 if (std::isnan(value)) {
976 root[
"value"] =
"\"NaN\"";
977 root[
"state"] =
"NA";
983 root[
"state"] =
state;
989#ifdef USE_DATETIME_DATE
997 if (obj->get_object_id() != match.
id)
999 if (request->method() == HTTP_GET && match.
method.empty()) {
1001 auto *param = request->getParam(
"detail");
1002 if (param && param->value() ==
"all") {
1005 std::string data = this->
date_json(obj, detail);
1006 request->send(200,
"application/json", data.c_str());
1009 if (match.
method !=
"set") {
1014 auto call = obj->make_call();
1016 if (!request->hasParam(
"value")) {
1021 if (request->hasParam(
"value")) {
1022 std::string value = request->getParam(
"value")->value().c_str();
1023 call.set_date(value);
1041 set_json_id(root, obj,
"date-" + obj->
get_object_id(), start_config);
1043 root[
"value"] = value;
1044 root[
"state"] = value;
1048 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1057#ifdef USE_DATETIME_TIME
1065 if (obj->get_object_id() != match.
id)
1067 if (request->method() == HTTP_GET && match.
method.empty()) {
1069 auto *param = request->getParam(
"detail");
1070 if (param && param->value() ==
"all") {
1073 std::string data = this->
time_json(obj, detail);
1074 request->send(200,
"application/json", data.c_str());
1077 if (match.
method !=
"set") {
1082 auto call = obj->make_call();
1084 if (!request->hasParam(
"value")) {
1089 if (request->hasParam(
"value")) {
1090 std::string value = request->getParam(
"value")->value().c_str();
1091 call.set_time(value);
1108 set_json_id(root, obj,
"time-" + obj->
get_object_id(), start_config);
1110 root[
"value"] = value;
1111 root[
"state"] = value;
1115 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1124#ifdef USE_DATETIME_DATETIME
1132 if (obj->get_object_id() != match.
id)
1134 if (request->method() == HTTP_GET && match.
method.empty()) {
1136 auto *param = request->getParam(
"detail");
1137 if (param && param->value() ==
"all") {
1141 request->send(200,
"application/json", data.c_str());
1144 if (match.
method !=
"set") {
1149 auto call = obj->make_call();
1151 if (!request->hasParam(
"value")) {
1156 if (request->hasParam(
"value")) {
1157 std::string value = request->getParam(
"value")->value().c_str();
1158 call.set_datetime(value);
1175 set_json_id(root, obj,
"datetime-" + obj->
get_object_id(), start_config);
1178 root[
"value"] = value;
1179 root[
"state"] = value;
1183 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1200 if (obj->get_object_id() != match.
id)
1203 if (request->method() == HTTP_GET && match.
method.empty()) {
1205 auto *param = request->getParam(
"detail");
1206 if (param && param->value() ==
"all") {
1209 std::string data = this->
text_json(obj, obj->state, detail);
1210 request->send(200,
"application/json", data.c_str());
1213 if (match.
method !=
"set") {
1218 auto call = obj->make_call();
1219 if (request->hasParam(
"value")) {
1220 String value = request->getParam(
"value")->value();
1221 call.set_value(value.c_str());
1238 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1239 set_json_id(root, obj,
"text-" + obj->
get_object_id(), start_config);
1244 root[
"state"] =
"********";
1246 root[
"state"] = value;
1248 root[
"value"] = value;
1253 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1270 if (obj->get_object_id() != match.
id)
1273 if (request->method() == HTTP_GET && match.
method.empty()) {
1275 auto *param = request->getParam(
"detail");
1276 if (param && param->value() ==
"all") {
1279 std::string data = this->
select_json(obj, obj->state, detail);
1280 request->send(200,
"application/json", data.c_str());
1284 if (match.
method !=
"set") {
1289 auto call = obj->make_call();
1291 if (request->hasParam(
"option")) {
1292 auto option = request->getParam(
"option")->value();
1293 call.set_option(option.c_str());
1309 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1310 set_json_icon_state_value(root, obj,
"select-" + obj->
get_object_id(), value, value, start_config);
1312 JsonArray opt = root.createNestedArray(
"option");
1318 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1328#define PSTR_LOCAL(mode_s) strncpy_P(buf, (PGM_P) ((mode_s)), 15)
1338 if (obj->get_object_id() != match.
id)
1341 if (request->method() == HTTP_GET && match.
method.empty()) {
1343 auto *param = request->getParam(
"detail");
1344 if (param && param->value() ==
"all") {
1348 request->send(200,
"application/json", data.c_str());
1352 if (match.
method !=
"set") {
1357 auto call = obj->make_call();
1359 if (request->hasParam(
"mode")) {
1360 auto mode = request->getParam(
"mode")->value();
1364 if (request->hasParam(
"fan_mode")) {
1365 auto mode = request->getParam(
"fan_mode")->value();
1369 if (request->hasParam(
"swing_mode")) {
1370 auto mode = request->getParam(
"swing_mode")->value();
1374 if (request->hasParam(
"target_temperature_high")) {
1380 if (request->hasParam(
"target_temperature_low")) {
1386 if (request->hasParam(
"target_temperature")) {
1406 set_json_id(root, obj,
"climate-" + obj->
get_object_id(), start_config);
1409 int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals();
1413 JsonArray opt = root.createNestedArray(
"modes");
1416 if (!traits.get_supported_custom_fan_modes().empty()) {
1417 JsonArray opt = root.createNestedArray(
"fan_modes");
1422 if (!traits.get_supported_custom_fan_modes().empty()) {
1423 JsonArray opt = root.createNestedArray(
"custom_fan_modes");
1424 for (
auto const &
custom_fan_mode : traits.get_supported_custom_fan_modes())
1427 if (traits.get_supports_swing_modes()) {
1428 JsonArray opt = root.createNestedArray(
"swing_modes");
1429 for (
auto swing_mode : traits.get_supported_swing_modes())
1433 JsonArray opt = root.createNestedArray(
"presets");
1438 JsonArray opt = root.createNestedArray(
"custom_presets");
1439 for (
auto const &
custom_preset : traits.get_supported_custom_presets())
1444 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1450 bool has_state =
false;
1451 root[
"mode"] = PSTR_LOCAL(climate_mode_to_string(obj->
mode));
1454 root[
"step"] = traits.get_visual_target_temperature_step();
1455 if (traits.get_supports_action()) {
1456 root[
"action"] = PSTR_LOCAL(climate_action_to_string(obj->
action));
1457 root[
"state"] = root[
"action"];
1461 root[
"fan_mode"] = PSTR_LOCAL(climate_fan_mode_to_string(obj->
fan_mode.
value()));
1467 root[
"preset"] = PSTR_LOCAL(climate_preset_to_string(obj->
preset.
value()));
1472 if (traits.get_supports_swing_modes()) {
1473 root[
"swing_mode"] = PSTR_LOCAL(climate_swing_mode_to_string(obj->
swing_mode));
1475 if (traits.get_supports_current_temperature()) {
1479 root[
"current_temperature"] =
"NA";
1482 if (traits.get_supports_two_point_target_temperature()) {
1492 root[
"state"] = root[
"target_temperature"];
1506 if (obj->get_object_id() != match.
id)
1509 if (request->method() == HTTP_GET && match.
method.empty()) {
1511 auto *param = request->getParam(
"detail");
1512 if (param && param->value() ==
"all") {
1515 std::string data = this->
lock_json(obj, obj->state, detail);
1516 request->send(200,
"application/json", data.c_str());
1517 }
else if (match.
method ==
"lock") {
1518 this->
schedule_([obj]() { obj->lock(); });
1520 }
else if (match.
method ==
"unlock") {
1521 this->
schedule_([obj]() { obj->unlock(); });
1523 }
else if (match.
method ==
"open") {
1524 this->
schedule_([obj]() { obj->open(); });
1540 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1546 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1563 if (obj->get_object_id() != match.
id)
1566 if (request->method() == HTTP_GET && match.
method.empty()) {
1568 auto *param = request->getParam(
"detail");
1569 if (param && param->value() ==
"all") {
1572 std::string data = this->
valve_json(obj, detail);
1573 request->send(200,
"application/json", data.c_str());
1577 auto call = obj->make_call();
1578 if (match.
method ==
"open") {
1579 call.set_command_open();
1580 }
else if (match.
method ==
"close") {
1581 call.set_command_close();
1582 }
else if (match.
method ==
"stop") {
1583 call.set_command_stop();
1584 }
else if (match.
method ==
"toggle") {
1585 call.set_command_toggle();
1586 }
else if (match.
method !=
"set") {
1591 auto traits = obj->get_traits();
1592 if (request->hasParam(
"position") && !traits.get_supports_position()) {
1597 if (request->hasParam(
"position")) {
1627 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1636#ifdef USE_ALARM_CONTROL_PANEL
1644 if (obj->get_object_id() != match.
id)
1647 if (request->method() == HTTP_GET && match.
method.empty()) {
1649 auto *param = request->getParam(
"detail");
1650 if (param && param->value() ==
"all") {
1654 request->send(200,
"application/json", data.c_str());
1658 auto call = obj->make_call();
1659 if (request->hasParam(
"code")) {
1660 call.set_code(request->getParam(
"code")->value().c_str());
1663 if (match.
method ==
"disarm") {
1665 }
else if (match.
method ==
"arm_away") {
1667 }
else if (match.
method ==
"arm_home") {
1669 }
else if (match.
method ==
"arm_night") {
1671 }
else if (match.
method ==
"arm_vacation") {
1672 call.arm_vacation();
1697 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1699 set_json_icon_state_value(root, obj,
"alarm-control-panel-" + obj->
get_object_id(),
1700 PSTR_LOCAL(alarm_control_panel_state_to_string(value)), value, start_config);
1704 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1720 if (obj->get_object_id() != match.
id)
1723 if (request->method() == HTTP_GET && match.
method.empty()) {
1725 auto *param = request->getParam(
"detail");
1726 if (param && param->value() ==
"all") {
1729 std::string data = this->
event_json(obj,
"", detail);
1730 request->send(200,
"application/json", data.c_str());
1737static std::string get_event_type(
event::Event *event) {
return event->last_event_type ? *
event->last_event_type :
""; }
1748 return json::build_json([
this, obj, event_type, start_config](JsonObject root) {
1749 set_json_id(root, obj,
"event-" + obj->
get_object_id(), start_config);
1750 if (!event_type.empty()) {
1751 root[
"event_type"] = event_type;
1754 JsonArray event_types = root.createNestedArray(
"event_types");
1756 event_types.add(event_type);
1761 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1778 if (obj->get_object_id() != match.
id)
1781 if (request->method() == HTTP_GET && match.
method.empty()) {
1783 auto *param = request->getParam(
"detail");
1784 if (param && param->value() ==
"all") {
1787 std::string data = this->
update_json(obj, detail);
1788 request->send(200,
"application/json", data.c_str());
1792 if (match.
method !=
"install") {
1797 this->
schedule_([obj]()
mutable { obj->perform(); });
1811 set_json_id(root, obj,
"update-" + obj->
get_object_id(), start_config);
1813 switch (obj->
state) {
1815 root[
"state"] =
"NO UPDATE";
1818 root[
"state"] =
"UPDATE AVAILABLE";
1821 root[
"state"] =
"INSTALLING";
1824 root[
"state"] =
"UNKNOWN";
1834 if (this->
sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
1844 if (request->url() ==
"/")
1848 if (request->url() ==
"/events") {
1853#ifdef USE_WEBSERVER_CSS_INCLUDE
1854 if (request->url() ==
"/0.css")
1858#ifdef USE_WEBSERVER_JS_INCLUDE
1859 if (request->url() ==
"/0.js")
1863#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
1864 if (request->method() == HTTP_OPTIONS && request->hasHeader(HEADER_CORS_REQ_PNA)) {
1869 request->addInterestingHeader(HEADER_CORS_REQ_PNA);
1879 if (request->method() == HTTP_GET && match.
domain ==
"sensor")
1884 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"switch")
1889 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"button")
1893#ifdef USE_BINARY_SENSOR
1894 if (request->method() == HTTP_GET && match.
domain ==
"binary_sensor")
1899 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"fan")
1904 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"light")
1908#ifdef USE_TEXT_SENSOR
1909 if (request->method() == HTTP_GET && match.
domain ==
"text_sensor")
1914 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"cover")
1919 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"number")
1923#ifdef USE_DATETIME_DATE
1924 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"date")
1928#ifdef USE_DATETIME_TIME
1929 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"time")
1933#ifdef USE_DATETIME_DATETIME
1934 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"datetime")
1939 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"text")
1944 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"select")
1949 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"climate")
1954 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"lock")
1959 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"valve")
1963#ifdef USE_ALARM_CONTROL_PANEL
1964 if ((request->method() == HTTP_GET || request->method() == HTTP_POST) && match.
domain ==
"alarm_control_panel")
1969 if (request->method() == HTTP_GET && match.
domain ==
"event")
1974 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"update")
1981 if (request->url() ==
"/") {
1987 if (request->url() ==
"/events") {
1993#ifdef USE_WEBSERVER_CSS_INCLUDE
1994 if (request->url() ==
"/0.css") {
2000#ifdef USE_WEBSERVER_JS_INCLUDE
2001 if (request->url() ==
"/0.js") {
2007#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
2008 if (request->method() == HTTP_OPTIONS && request->hasHeader(HEADER_CORS_REQ_PNA)) {
2016 if (match.
domain ==
"sensor") {
2023 if (match.
domain ==
"switch") {
2030 if (match.
domain ==
"button") {
2036#ifdef USE_BINARY_SENSOR
2037 if (match.
domain ==
"binary_sensor") {
2044 if (match.
domain ==
"fan") {
2051 if (match.
domain ==
"light") {
2057#ifdef USE_TEXT_SENSOR
2058 if (match.
domain ==
"text_sensor") {
2065 if (match.
domain ==
"cover") {
2072 if (match.
domain ==
"number") {
2078#ifdef USE_DATETIME_DATE
2079 if (match.
domain ==
"date") {
2085#ifdef USE_DATETIME_TIME
2086 if (match.
domain ==
"time") {
2092#ifdef USE_DATETIME_DATETIME
2093 if (match.
domain ==
"datetime") {
2100 if (match.
domain ==
"text") {
2107 if (match.
domain ==
"select") {
2114 if (match.
domain ==
"climate") {
2121 if (match.
domain ==
"lock") {
2129 if (match.
domain ==
"valve") {
2135#ifdef USE_ALARM_CONTROL_PANEL
2136 if (match.
domain ==
"alarm_control_panel") {
2144 if (match.
domain ==
"update") {
2167 this->
defer(std::move(f));
BedjetMode mode
BedJet operating mode.
std::string get_comment() const
Get the comment of this Application set by pre_setup().
const std::string & get_friendly_name() const
Get the friendly name of this Application set by pre_setup().
const std::vector< button::Button * > & get_buttons()
const std::vector< datetime::TimeEntity * > & get_times()
const std::vector< valve::Valve * > & get_valves()
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< datetime::DateTimeEntity * > & get_datetimes()
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::vector< update::UpdateEntity * > & get_updates()
const std::string & get_name() const
Get the name of this Application set by pre_setup().
const std::vector< datetime::DateEntity * > & get_dates()
const std::vector< alarm_control_panel::AlarmControlPanel * > & get_alarm_control_panels()
const std::vector< cover::Cover * > & get_covers()
const std::vector< binary_sensor::BinarySensor * > & get_binary_sensors()
const std::vector< event::Event * > & get_events()
const std::vector< number::Number * > & get_numbers()
void set_interval(const std::string &name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
void begin(bool include_internal=false)
void setup_controller(bool include_internal=false)
std::string get_device_class()
Get the device class, using the manual override if set.
std::string get_unit_of_measurement()
Get the unit of measurement, using the manual override if set.
std::string get_object_id() const
Base class for all binary_sensor-type classes.
ClimateDevice - This is the base class for all climate integrations.
ClimateMode mode
The active mode of the climate device.
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
float target_temperature
The target temperature of the climate device.
optional< std::string > custom_fan_mode
The active custom fan mode of the climate device.
ClimateSwingMode swing_mode
The active swing mode of the climate device.
float target_temperature_low
The minimum target temperature of the climate device, for climate devices with split target temperatu...
optional< std::string > custom_preset
The active custom preset mode of the climate device.
float current_temperature
The current temperature of the climate device, as reported from the integration.
ClimateAction action
The active state of the climate device.
optional< ClimatePreset > preset
The active preset of the climate device.
float target_temperature_high
The maximum target temperature of the climate device, for climate devices with split target temperatu...
int8_t get_target_temperature_accuracy_decimals() const
Base class for all cover devices.
CoverOperation current_operation
The current operation of the cover (idle, opening, closing).
float tilt
The current tilt value of the cover from 0.0 to 1.0.
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
bool is_fully_closed() const
Helper method to check if the cover is fully closed. Equivalent to comparing .position against 0....
virtual CoverTraits get_traits()=0
bool get_supports_position() const
bool get_supports_tilt() const
std::set< std::string > get_event_types() const
virtual FanTraits get_traits()=0
bool oscillating
The current oscillation state of the fan.
bool state
The current on/off state of the fan.
int speed
The current fan speed level.
bool supports_oscillation() const
Return if this fan supports oscillation.
bool is_on() const
Get the binary true/false state of these light color values.
static void dump_json(LightState &state, JsonObject root)
Dump the state of a light as JSON.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
const std::vector< LightEffect * > & get_effects() const
Get all effects for this light state.
LightColorValues remote_values
The remote color values reported to the frontend.
Base class for all locks.
void add_on_log_callback(std::function< void(int, const char *, const char *)> &&callback)
Register a callback that will be called for every log message sent.
Base-class for all numbers.
float get_min_value() const
float get_max_value() const
NumberMode get_mode() const
value_type const & value() const
Base-class for all selects.
std::vector< std::string > get_options() const
Base-class for all sensors.
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
Base class for all switches.
virtual bool assumed_state()
Return whether this switch uses an assumed state - i.e.
Base-class for all text inputs.
TextMode get_mode() const
int get_max_length() const
std::string get_pattern() const
int get_min_length() const
const UpdateState & state
const UpdateInfo & update_info
Base class for all valve devices.
bool is_fully_closed() const
Helper method to check if the valve is fully closed. Equivalent to comparing .position against 0....
float position
The position of the valve from 0.0 (fully closed) to 1.0 (fully open).
ValveOperation current_operation
The current operation of the valve (idle, opening, closing).
virtual ValveTraits get_traits()=0
bool get_supports_position() const
void process_deferred_queue_()
void try_send_nodefer(const char *message, const char *event=nullptr, uint32_t id=0, uint32_t reconnect=0)
void deq_push_back_with_dedup_(void *source, message_generator_t *message_generator)
void deferrable_send_state(void *source, const char *event_type, message_generator_t *message_generator)
ListEntitiesIterator entities_iterator_
std::vector< DeferredEvent > deferred_queue_
void add_new_client(WebServer *ws, AsyncWebServerRequest *request)
void deferrable_send_state(void *source, const char *event_type, message_generator_t *message_generator)
void try_send_nodefer(const char *message, const char *event=nullptr, uint32_t id=0, uint32_t reconnect=0)
void on_client_connect_(WebServer *ws, DeferredUpdateEventSource *source)
void on_client_disconnect_(DeferredUpdateEventSource *source)
This class allows users to create a web server with their ESP nodes.
void setup() override
Setup the internal web server and register handlers.
void on_update(update::UpdateEntity *obj) override
static std::string text_sensor_all_json_generator(WebServer *web_server, void *source)
std::string light_json(light::LightState *obj, JsonDetail start_config)
Dump the light state as a JSON string.
bool canHandle(AsyncWebServerRequest *request) override
Override the web handler's canHandle method.
std::string date_json(datetime::DateEntity *obj, JsonDetail start_config)
Dump the date state with its value as a JSON string.
std::string get_config_json()
Return the webserver configuration as JSON.
std::map< EntityBase *, SortingComponents > sorting_entitys_
static std::string binary_sensor_state_json_generator(WebServer *web_server, void *source)
std::string binary_sensor_json(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config)
Dump the binary sensor state with its value as a JSON string.
static std::string button_state_json_generator(WebServer *web_server, void *source)
static std::string lock_all_json_generator(WebServer *web_server, void *source)
std::deque< std::function< void()> > to_schedule_
void on_light_update(light::LightState *obj) override
static std::string date_all_json_generator(WebServer *web_server, void *source)
std::string update_json(update::UpdateEntity *obj, JsonDetail start_config)
Dump the update state with its value as a JSON string.
void on_cover_update(cover::Cover *obj) override
static std::string text_state_json_generator(WebServer *web_server, void *source)
void handle_select_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a select request under '/select/<id>'.
void schedule_(std::function< void()> &&f)
std::string number_json(number::Number *obj, float value, JsonDetail start_config)
Dump the number state with its value as a JSON string.
static std::string event_state_json_generator(WebServer *web_server, void *source)
std::string cover_json(cover::Cover *obj, JsonDetail start_config)
Dump the cover state as a JSON string.
static std::string datetime_all_json_generator(WebServer *web_server, void *source)
static std::string sensor_all_json_generator(WebServer *web_server, void *source)
WebServer(web_server_base::WebServerBase *base)
std::string text_sensor_json(text_sensor::TextSensor *obj, const std::string &value, JsonDetail start_config)
Dump the text sensor state with its value as a JSON string.
void on_number_update(number::Number *obj, float state) override
void handle_switch_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a switch request under '/switch/<id>/</turn_on/turn_off/toggle>'.
void handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a event request under '/event<id>'.
void dump_config() override
std::string button_json(button::Button *obj, JsonDetail start_config)
Dump the button details with its value as a JSON string.
std::string valve_json(valve::Valve *obj, JsonDetail start_config)
Dump the valve state as a JSON string.
DeferredUpdateEventSourceList events_
void handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a button request under '/button/<id>/press'.
void on_date_update(datetime::DateEntity *obj) override
std::string text_json(text::Text *obj, const std::string &value, JsonDetail start_config)
Dump the text state with its value as a JSON string.
void add_entity_config(EntityBase *entity, float weight, uint64_t group)
bool isRequestHandlerTrivial() override
This web handle is not trivial.
std::string datetime_json(datetime::DateTimeEntity *obj, JsonDetail start_config)
Dump the datetime state with its value as a JSON string.
void handle_css_request(AsyncWebServerRequest *request)
Handle included css request under '/0.css'.
static std::string sensor_state_json_generator(WebServer *web_server, void *source)
void on_valve_update(valve::Valve *obj) override
void on_climate_update(climate::Climate *obj) override
void on_sensor_update(sensor::Sensor *obj, float state) override
static std::string switch_state_json_generator(WebServer *web_server, void *source)
void handle_light_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a light request under '/light/<id>/</turn_on/turn_off/toggle>'.
static std::string event_all_json_generator(WebServer *web_server, void *source)
static std::string climate_state_json_generator(WebServer *web_server, void *source)
static std::string number_all_json_generator(WebServer *web_server, void *source)
void handle_text_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a text input request under '/text/<id>'.
SemaphoreHandle_t to_schedule_lock_
void handle_cover_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a cover request under '/cover/<id>/<open/close/stop/set>'.
void on_select_update(select::Select *obj, const std::string &state, size_t index) override
static std::string date_state_json_generator(WebServer *web_server, void *source)
static std::string valve_all_json_generator(WebServer *web_server, void *source)
static std::string text_all_json_generator(WebServer *web_server, void *source)
web_server_base::WebServerBase * base_
static std::string binary_sensor_all_json_generator(WebServer *web_server, void *source)
static std::string light_state_json_generator(WebServer *web_server, void *source)
void handle_lock_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a lock request under '/lock/<id>/</lock/unlock/open>'.
void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) override
static std::string light_all_json_generator(WebServer *web_server, void *source)
void on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool state) override
std::string switch_json(switch_::Switch *obj, bool value, JsonDetail start_config)
Dump the switch state with its value as a JSON string.
void handle_text_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a text sensor request under '/text_sensor/<id>'.
std::string sensor_json(sensor::Sensor *obj, float value, JsonDetail start_config)
Dump the sensor state with its value as a JSON string.
void handle_date_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a date request under '/date/<id>'.
static std::string cover_all_json_generator(WebServer *web_server, void *source)
void handle_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a sensor request under '/sensor/<id>'.
static std::string text_sensor_state_json_generator(WebServer *web_server, void *source)
void handle_number_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a number request under '/number/<id>'.
static std::string alarm_control_panel_state_json_generator(WebServer *web_server, void *source)
void handle_index_request(AsyncWebServerRequest *request)
Handle an index request under '/'.
void handle_js_request(AsyncWebServerRequest *request)
Handle included js request under '/0.js'.
void set_js_include(const char *js_include)
Set local path to the script that's embedded in the index page.
void on_text_update(text::Text *obj, const std::string &state) override
static std::string fan_state_json_generator(WebServer *web_server, void *source)
static std::string update_state_json_generator(WebServer *web_server, void *source)
void handleRequest(AsyncWebServerRequest *request) override
Override the web handler's handleRequest method.
static std::string climate_all_json_generator(WebServer *web_server, void *source)
void on_datetime_update(datetime::DateTimeEntity *obj) override
std::string event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config)
Dump the event details with its value as a JSON string.
void on_text_sensor_update(text_sensor::TextSensor *obj, const std::string &state) override
std::string time_json(datetime::TimeEntity *obj, JsonDetail start_config)
Dump the time state with its value as a JSON string.
void handle_fan_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a fan request under '/fan/<id>/</turn_on/turn_off/toggle>'.
static std::string cover_state_json_generator(WebServer *web_server, void *source)
static std::string lock_state_json_generator(WebServer *web_server, void *source)
void handle_valve_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a valve request under '/valve/<id>/<open/close/stop/set>'.
void handle_binary_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a binary sensor request under '/binary_sensor/<id>'.
static std::string alarm_control_panel_all_json_generator(WebServer *web_server, void *source)
static std::string number_state_json_generator(WebServer *web_server, void *source)
void handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a time request under '/time/<id>'.
std::map< uint64_t, SortingGroup > sorting_groups_
void set_css_include(const char *css_include)
Set local path to the script that's embedded in the index page.
static std::string valve_state_json_generator(WebServer *web_server, void *source)
std::string lock_json(lock::Lock *obj, lock::LockState value, JsonDetail start_config)
Dump the lock state with its value as a JSON string.
void handle_pna_cors_request(AsyncWebServerRequest *request)
std::string fan_json(fan::Fan *obj, JsonDetail start_config)
Dump the fan state as a JSON string.
void on_fan_update(fan::Fan *obj) override
void handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a datetime request under '/datetime/<id>'.
void on_event(event::Event *obj, const std::string &event_type) override
void handle_alarm_control_panel_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a alarm_control_panel request under '/alarm_control_panel/<id>'.
static std::string time_state_json_generator(WebServer *web_server, void *source)
void on_lock_update(lock::Lock *obj) override
static std::string button_all_json_generator(WebServer *web_server, void *source)
static std::string select_state_json_generator(WebServer *web_server, void *source)
float get_setup_priority() const override
MQTT setup priority.
void on_time_update(datetime::TimeEntity *obj) override
std::string select_json(select::Select *obj, const std::string &value, JsonDetail start_config)
Dump the select state with its value as a JSON string.
static std::string update_all_json_generator(WebServer *web_server, void *source)
void on_switch_update(switch_::Switch *obj, bool state) override
void handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a update request under '/update/<id>'.
std::string climate_json(climate::Climate *obj, JsonDetail start_config)
Dump the climate details.
static std::string fan_all_json_generator(WebServer *web_server, void *source)
static std::string switch_all_json_generator(WebServer *web_server, void *source)
static std::string time_all_json_generator(WebServer *web_server, void *source)
void add_sorting_group(uint64_t group_id, const std::string &group_name, float weight)
static std::string select_all_json_generator(WebServer *web_server, void *source)
const char * css_include_
static std::string datetime_state_json_generator(WebServer *web_server, void *source)
void handle_climate_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a climate request under '/climate/<id>'.
std::string alarm_control_panel_json(alarm_control_panel::AlarmControlPanel *obj, alarm_control_panel::AlarmControlPanelState value, JsonDetail start_config)
Dump the alarm_control_panel state with its value as a JSON string.
void add_handler(AsyncWebHandler *handler)
uint16_t get_port() const
float target_temperature_high
ClimateSwingMode swing_mode
float target_temperature_low
const LogString * climate_swing_mode_to_string(ClimateSwingMode swing_mode)
Convert the given ClimateSwingMode to a human-readable string.
const LogString * climate_preset_to_string(ClimatePreset preset)
Convert the given PresetMode to a human-readable string.
ClimatePreset
Enum for all preset modes.
const LogString * climate_fan_mode_to_string(ClimateFanMode fan_mode)
Convert the given ClimateFanMode to a human-readable string.
ClimateMode
Enum for all modes a climate device can be in.
const LogString * climate_mode_to_string(ClimateMode mode)
Convert the given ClimateMode to a human-readable string.
const char * cover_operation_to_str(CoverOperation op)
std::string build_json(const json_build_t &f)
Build a JSON string with the provided json build function.
LockState
Enum for all states a lock can be in.
const char * lock_state_to_string(LockState state)
std::string get_use_address()
Get the active network hostname.
@ UPDATE_STATE_INSTALLING
const char * valve_operation_to_str(ValveOperation op)
std::string(WebServer *, void *) message_generator_t
UrlMatch match_url(const std::string &url, bool only_domain=false)
Providing packet encoding functions for exchanging data with a remote host.
std::string value_accuracy_to_string(float value, int8_t accuracy_decimals)
Create a string from a value and an accuracy in decimals.
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
int8_t step_to_accuracy_decimals(float step)
Derive accuracy in decimals from an increment step.
std::string str_sprintf(const char *fmt,...)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
std::string current_version
std::string latest_version
Internal helper struct that is used to parse incoming URLs.
bool valid
Whether this match is valid.
std::string domain
The domain of the component, for example "sensor".
std::string id
The id of the device that's being accessed, for example "living_room_fan".
std::string method
The method that's being called, for example "turn_on".
friend class DeferredUpdateEventSource
const size_t ESPHOME_WEBSERVER_INDEX_HTML_SIZE
const size_t ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE
const size_t ESPHOME_WEBSERVER_JS_INCLUDE_SIZE