12 #include "StreamString.h" 29 #ifdef USE_WEBSERVER_LOCAL 30 #if USE_WEBSERVER_VERSION == 2 32 #elif USE_WEBSERVER_VERSION == 3 38 namespace web_server {
40 static const char *
const TAG =
"web_server";
42 #ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS 43 static const char *
const HEADER_PNA_NAME =
"Private-Network-Access-Name";
44 static const char *
const HEADER_PNA_ID =
"Private-Network-Access-ID";
45 static const char *
const HEADER_CORS_REQ_PNA =
"Access-Control-Request-Private-Network";
46 static 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);
82 #ifdef USE_WEBSERVER_CSS_INCLUDE 85 #ifdef USE_WEBSERVER_JS_INCLUDE 100 ESP_LOGCONFIG(TAG,
"Setting up web server...");
110 root[
"name"] = group.second.name;
111 root[
"sorting_weight"] = group.second.weight;
122 [
this](
int level,
const char *tag,
const char *message) { this->
events_.send(message,
"log",
millis()); });
136 std::function<void()> fn;
153 ESP_LOGCONFIG(TAG,
"Web Server:");
158 #ifdef USE_WEBSERVER_LOCAL 160 AsyncWebServerResponse *response = request->beginResponse_P(200,
"text/html", INDEX_GZ,
sizeof(INDEX_GZ));
161 response->addHeader(
"Content-Encoding",
"gzip");
162 request->send(response);
164 #elif USE_WEBSERVER_VERSION >= 2 166 AsyncWebServerResponse *response =
169 request->send(response);
173 #ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS 175 AsyncWebServerResponse *response = request->beginResponse(200,
"");
176 response->addHeader(HEADER_CORS_ALLOW_PNA,
"true");
177 response->addHeader(HEADER_PNA_NAME,
App.
get_name().c_str());
179 response->addHeader(HEADER_PNA_ID, mac.c_str());
180 request->send(response);
184 #ifdef USE_WEBSERVER_CSS_INCLUDE 186 AsyncWebServerResponse *response =
188 response->addHeader(
"Content-Encoding",
"gzip");
189 request->send(response);
193 #ifdef USE_WEBSERVER_JS_INCLUDE 195 AsyncWebServerResponse *response =
197 response->addHeader(
"Content-Encoding",
"gzip");
198 request->send(response);
202 #define set_json_id(root, obj, sensor, start_config) \ 203 (root)["id"] = sensor; \ 204 if (((start_config) == DETAIL_ALL)) { \ 205 (root)["name"] = (obj)->get_name(); \ 206 (root)["icon"] = (obj)->get_icon(); \ 207 (root)["entity_category"] = (obj)->get_entity_category(); \ 208 if ((obj)->is_disabled_by_default()) \ 209 (root)["is_disabled_by_default"] = (obj)->is_disabled_by_default(); \ 212 #define set_json_value(root, obj, sensor, value, start_config) \ 213 set_json_id((root), (obj), sensor, start_config); \ 214 (root)["value"] = value; 216 #define set_json_icon_state_value(root, obj, sensor, state, value, start_config) \ 217 set_json_value(root, obj, sensor, value, start_config); \ 218 (root)["state"] = state; 222 if (this->
events_.count() == 0)
228 if (obj->get_object_id() != match.
id)
230 if (request->method() == HTTP_GET && match.
method.empty()) {
232 auto *param = request->getParam(
"detail");
233 if (param && param->value() ==
"all") {
236 std::string data = this->
sensor_json(obj, obj->state, detail);
237 request->send(200,
"application/json", data.c_str());
246 if (std::isnan(value)) {
253 set_json_icon_state_value(root, obj,
"sensor-" + obj->
get_object_id(),
state, value, start_config);
268 #ifdef USE_TEXT_SENSOR 270 if (this->
events_.count() == 0)
276 if (obj->get_object_id() != match.
id)
278 if (request->method() == HTTP_GET && match.
method.empty()) {
280 auto *param = request->getParam(
"detail");
281 if (param && param->value() ==
"all") {
285 request->send(200,
"application/json", data.c_str());
294 set_json_icon_state_value(root, obj,
"text_sensor-" + obj->
get_object_id(), value, value, start_config);
309 if (this->
events_.count() == 0)
315 if (obj->get_object_id() != match.
id)
318 if (request->method() == HTTP_GET && match.
method.empty()) {
320 auto *param = request->getParam(
"detail");
321 if (param && param->value() ==
"all") {
324 std::string data = this->
switch_json(obj, obj->state, detail);
325 request->send(200,
"application/json", data.c_str());
326 }
else if (match.
method ==
"toggle") {
327 this->
schedule_([obj]() { obj->toggle(); });
329 }
else if (match.
method ==
"turn_on") {
330 this->
schedule_([obj]() { obj->turn_on(); });
332 }
else if (match.
method ==
"turn_off") {
333 this->
schedule_([obj]() { obj->turn_off(); });
344 set_json_icon_state_value(root, obj,
"switch-" + obj->
get_object_id(), value ?
"ON" :
"OFF", value, start_config);
361 if (obj->get_object_id() != match.
id)
363 if (request->method() == HTTP_GET && match.
method.empty()) {
365 auto *param = request->getParam(
"detail");
366 if (param && param->value() ==
"all") {
370 request->send(200,
"application/json", data.c_str());
371 }
else if (match.
method ==
"press") {
372 this->
schedule_([obj]() { obj->press(); });
384 set_json_id(root, obj,
"button-" + obj->
get_object_id(), start_config);
397 #ifdef USE_BINARY_SENSOR 399 if (this->
events_.count() == 0)
405 if (obj->get_object_id() != match.
id)
407 if (request->method() == HTTP_GET && match.
method.empty()) {
409 auto *param = request->getParam(
"detail");
410 if (param && param->value() ==
"all") {
414 request->send(200,
"application/json", data.c_str());
422 set_json_icon_state_value(root, obj,
"binary_sensor-" + obj->
get_object_id(), value ?
"ON" :
"OFF", value,
438 if (this->
events_.count() == 0)
444 if (obj->get_object_id() != match.
id)
447 if (request->method() == HTTP_GET && match.
method.empty()) {
449 auto *param = request->getParam(
"detail");
450 if (param && param->value() ==
"all") {
453 std::string data = this->
fan_json(obj, detail);
454 request->send(200,
"application/json", data.c_str());
455 }
else if (match.
method ==
"toggle") {
456 this->
schedule_([obj]() { obj->toggle().perform(); });
458 }
else if (match.
method ==
"turn_on" || match.
method ==
"turn_off") {
459 auto call = match.
method ==
"turn_on" ? obj->turn_on() : obj->turn_off();
461 if (request->hasParam(
"speed_level")) {
462 auto speed_level = request->getParam(
"speed_level")->value();
463 auto val = parse_number<int>(speed_level.c_str());
464 if (!
val.has_value()) {
465 ESP_LOGW(TAG,
"Can't convert '%s' to number!", speed_level.c_str());
470 if (request->hasParam(
"oscillation")) {
471 auto speed = request->getParam(
"oscillation")->value();
475 call.set_oscillating(
true);
478 call.set_oscillating(
false);
481 call.set_oscillating(!obj->oscillating);
502 if (traits.supports_speed()) {
503 root[
"speed_level"] = obj->
speed;
504 root[
"speed_count"] = traits.supported_speed_count();
522 if (this->
events_.count() == 0)
528 if (obj->get_object_id() != match.
id)
531 if (request->method() == HTTP_GET && match.
method.empty()) {
533 auto *param = request->getParam(
"detail");
534 if (param && param->value() ==
"all") {
537 std::string data = this->
light_json(obj, detail);
538 request->send(200,
"application/json", data.c_str());
539 }
else if (match.
method ==
"toggle") {
540 this->
schedule_([obj]() { obj->toggle().perform(); });
542 }
else if (match.
method ==
"turn_on") {
543 auto call = obj->turn_on();
544 if (request->hasParam(
"brightness")) {
545 auto brightness = parse_number<float>(request->getParam(
"brightness")->value().c_str());
546 if (brightness.has_value()) {
547 call.set_brightness(*brightness / 255.0f);
550 if (request->hasParam(
"r")) {
551 auto r = parse_number<float>(request->getParam(
"r")->value().c_str());
553 call.set_red(*r / 255.0f);
556 if (request->hasParam(
"g")) {
557 auto g = parse_number<float>(request->getParam(
"g")->value().c_str());
559 call.set_green(*g / 255.0f);
562 if (request->hasParam(
"b")) {
563 auto b = parse_number<float>(request->getParam(
"b")->value().c_str());
565 call.set_blue(*b / 255.0f);
568 if (request->hasParam(
"white_value")) {
569 auto white_value = parse_number<float>(request->getParam(
"white_value")->value().c_str());
570 if (white_value.has_value()) {
571 call.set_white(*white_value / 255.0f);
574 if (request->hasParam(
"color_temp")) {
575 auto color_temp = parse_number<float>(request->getParam(
"color_temp")->value().c_str());
576 if (color_temp.has_value()) {
577 call.set_color_temperature(*color_temp);
580 if (request->hasParam(
"flash")) {
581 auto flash = parse_number<uint32_t>(request->getParam(
"flash")->value().c_str());
582 if (flash.has_value()) {
583 call.set_flash_length(*flash * 1000);
586 if (request->hasParam(
"transition")) {
587 auto transition = parse_number<uint32_t>(request->getParam(
"transition")->value().c_str());
588 if (transition.has_value()) {
589 call.set_transition_length(*transition * 1000);
592 if (request->hasParam(
"effect")) {
593 const char *effect = request->getParam(
"effect")->value().c_str();
594 call.set_effect(effect);
599 }
else if (match.
method ==
"turn_off") {
600 auto call = obj->turn_off();
601 if (request->hasParam(
"transition")) {
602 auto transition = parse_number<uint32_t>(request->getParam(
"transition")->value().c_str());
603 if (transition.has_value()) {
604 call.set_transition_length(*transition * 1000);
618 set_json_id(root, obj,
"light-" + obj->
get_object_id(), start_config);
623 JsonArray opt = root.createNestedArray(
"effects");
626 opt.add(option->get_name());
641 if (this->
events_.count() == 0)
647 if (obj->get_object_id() != match.
id)
650 if (request->method() == HTTP_GET && match.
method.empty()) {
652 auto *param = request->getParam(
"detail");
653 if (param && param->value() ==
"all") {
656 std::string data = this->
cover_json(obj, detail);
657 request->send(200,
"application/json", data.c_str());
661 auto call = obj->make_call();
662 if (match.
method ==
"open") {
663 call.set_command_open();
664 }
else if (match.
method ==
"close") {
665 call.set_command_close();
666 }
else if (match.
method ==
"stop") {
667 call.set_command_stop();
668 }
else if (match.
method ==
"toggle") {
669 call.set_command_toggle();
670 }
else if (match.
method !=
"set") {
675 auto traits = obj->get_traits();
676 if ((request->hasParam(
"position") && !traits.get_supports_position()) ||
677 (request->hasParam(
"tilt") && !traits.get_supports_tilt())) {
682 if (request->hasParam(
"position")) {
683 auto position = parse_number<float>(request->getParam(
"position")->value().c_str());
688 if (request->hasParam(
"tilt")) {
689 auto tilt = parse_number<float>(request->getParam(
"tilt")->value().c_str());
690 if (
tilt.has_value()) {
710 root[
"tilt"] = obj->
tilt;
725 if (this->
events_.count() == 0)
731 if (obj->get_object_id() != match.
id)
734 if (request->method() == HTTP_GET && match.
method.empty()) {
736 auto *param = request->getParam(
"detail");
737 if (param && param->value() ==
"all") {
740 std::string data = this->
number_json(obj, obj->state, detail);
741 request->send(200,
"application/json", data.c_str());
744 if (match.
method !=
"set") {
749 auto call = obj->make_call();
750 if (request->hasParam(
"value")) {
751 auto value = parse_number<float>(request->getParam(
"value")->value().c_str());
752 if (value.has_value())
753 call.set_value(*value);
765 set_json_id(root, obj,
"number-" + obj->
get_object_id(), start_config);
783 if (std::isnan(value)) {
784 root[
"value"] =
"\"NaN\"";
785 root[
"state"] =
"NA";
791 root[
"state"] =
state;
797 #ifdef USE_DATETIME_DATE 799 if (this->
events_.count() == 0)
805 if (obj->get_object_id() != match.
id)
807 if (request->method() == HTTP_GET && match.
method.empty()) {
809 auto *param = request->getParam(
"detail");
810 if (param && param->value() ==
"all") {
813 std::string data = this->
date_json(obj, detail);
814 request->send(200,
"application/json", data.c_str());
817 if (match.
method !=
"set") {
822 auto call = obj->make_call();
824 if (!request->hasParam(
"value")) {
829 if (request->hasParam(
"value")) {
830 std::string value = request->getParam(
"value")->value().c_str();
831 call.set_date(value);
843 set_json_id(root, obj,
"date-" + obj->
get_object_id(), start_config);
845 root[
"value"] = value;
846 root[
"state"] = value;
857 #endif // USE_DATETIME_DATE 859 #ifdef USE_DATETIME_TIME 861 if (this->
events_.count() == 0)
867 if (obj->get_object_id() != match.
id)
869 if (request->method() == HTTP_GET && match.
method.empty()) {
871 auto *param = request->getParam(
"detail");
872 if (param && param->value() ==
"all") {
875 std::string data = this->
time_json(obj, detail);
876 request->send(200,
"application/json", data.c_str());
879 if (match.
method !=
"set") {
884 auto call = obj->make_call();
886 if (!request->hasParam(
"value")) {
891 if (request->hasParam(
"value")) {
892 std::string value = request->getParam(
"value")->value().c_str();
893 call.set_time(value);
904 set_json_id(root, obj,
"time-" + obj->
get_object_id(), start_config);
906 root[
"value"] = value;
907 root[
"state"] = value;
918 #endif // USE_DATETIME_TIME 920 #ifdef USE_DATETIME_DATETIME 922 if (this->
events_.count() == 0)
928 if (obj->get_object_id() != match.
id)
930 if (request->method() == HTTP_GET && match.
method.empty()) {
932 auto *param = request->getParam(
"detail");
933 if (param && param->value() ==
"all") {
937 request->send(200,
"application/json", data.c_str());
940 if (match.
method !=
"set") {
945 auto call = obj->make_call();
947 if (!request->hasParam(
"value")) {
952 if (request->hasParam(
"value")) {
953 std::string value = request->getParam(
"value")->value().c_str();
954 call.set_datetime(value);
965 set_json_id(root, obj,
"datetime-" + obj->
get_object_id(), start_config);
968 root[
"value"] = value;
969 root[
"state"] = value;
980 #endif // USE_DATETIME_DATETIME 984 if (this->
events_.count() == 0)
990 if (obj->get_object_id() != match.
id)
993 if (request->method() == HTTP_GET && match.
method.empty()) {
995 auto *param = request->getParam(
"detail");
996 if (param && param->value() ==
"all") {
999 std::string data = this->
text_json(obj, obj->state, detail);
1000 request->send(200,
"application/json", data.c_str());
1003 if (match.
method !=
"set") {
1008 auto call = obj->make_call();
1009 if (request->hasParam(
"value")) {
1010 String value = request->getParam(
"value")->value();
1011 call.set_value(value.c_str());
1022 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1023 set_json_id(root, obj,
"text-" + obj->
get_object_id(), start_config);
1028 root[
"state"] =
"********";
1030 root[
"state"] = value;
1032 root[
"value"] = value;
1048 if (this->
events_.count() == 0)
1054 if (obj->get_object_id() != match.
id)
1057 if (request->method() == HTTP_GET && match.
method.empty()) {
1059 auto *param = request->getParam(
"detail");
1060 if (param && param->value() ==
"all") {
1063 std::string data = this->
select_json(obj, obj->state, detail);
1064 request->send(200,
"application/json", data.c_str());
1068 if (match.
method !=
"set") {
1073 auto call = obj->make_call();
1075 if (request->hasParam(
"option")) {
1076 auto option = request->getParam(
"option")->value();
1077 call.set_option(option.c_str());
1087 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1088 set_json_icon_state_value(root, obj,
"select-" + obj->
get_object_id(), value, value, start_config);
1090 JsonArray opt = root.createNestedArray(
"option");
1106 #define PSTR_LOCAL(mode_s) strncpy_P(buf, (PGM_P) ((mode_s)), 15) 1110 if (this->
events_.count() == 0)
1116 if (obj->get_object_id() != match.
id)
1119 if (request->method() == HTTP_GET && match.
method.empty()) {
1121 auto *param = request->getParam(
"detail");
1122 if (param && param->value() ==
"all") {
1126 request->send(200,
"application/json", data.c_str());
1129 if (match.
method !=
"set") {
1134 auto call = obj->make_call();
1136 if (request->hasParam(
"mode")) {
1137 auto mode = request->getParam(
"mode")->value();
1141 if (request->hasParam(
"fan_mode")) {
1142 auto mode = request->getParam(
"fan_mode")->value();
1146 if (request->hasParam(
"swing_mode")) {
1147 auto mode = request->getParam(
"swing_mode")->value();
1151 if (request->hasParam(
"target_temperature_high")) {
1152 auto target_temperature_high = parse_number<float>(request->getParam(
"target_temperature_high")->value().c_str());
1157 if (request->hasParam(
"target_temperature_low")) {
1158 auto target_temperature_low = parse_number<float>(request->getParam(
"target_temperature_low")->value().c_str());
1163 if (request->hasParam(
"target_temperature")) {
1164 auto target_temperature = parse_number<float>(request->getParam(
"target_temperature")->value().c_str());
1177 set_json_id(root, obj,
"climate-" + obj->
get_object_id(), start_config);
1180 int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals();
1184 JsonArray opt = root.createNestedArray(
"modes");
1187 if (!traits.get_supported_custom_fan_modes().empty()) {
1188 JsonArray opt = root.createNestedArray(
"fan_modes");
1193 if (!traits.get_supported_custom_fan_modes().empty()) {
1194 JsonArray opt = root.createNestedArray(
"custom_fan_modes");
1195 for (
auto const &
custom_fan_mode : traits.get_supported_custom_fan_modes())
1198 if (traits.get_supports_swing_modes()) {
1199 JsonArray opt = root.createNestedArray(
"swing_modes");
1200 for (
auto swing_mode : traits.get_supported_swing_modes())
1204 JsonArray opt = root.createNestedArray(
"presets");
1209 JsonArray opt = root.createNestedArray(
"custom_presets");
1210 for (
auto const &
custom_preset : traits.get_supported_custom_presets())
1221 bool has_state =
false;
1225 root[
"step"] = traits.get_visual_target_temperature_step();
1226 if (traits.get_supports_action()) {
1228 root[
"state"] = root[
"action"];
1243 if (traits.get_supports_swing_modes()) {
1246 if (traits.get_supports_current_temperature()) {
1250 root[
"current_temperature"] =
"NA";
1253 if (traits.get_supports_two_point_target_temperature()) {
1263 root[
"state"] = root[
"target_temperature"];
1271 if (this->
events_.count() == 0)
1277 if (obj->get_object_id() != match.
id)
1280 if (request->method() == HTTP_GET && match.
method.empty()) {
1282 auto *param = request->getParam(
"detail");
1283 if (param && param->value() ==
"all") {
1286 std::string data = this->
lock_json(obj, obj->state, detail);
1287 request->send(200,
"application/json", data.c_str());
1288 }
else if (match.
method ==
"lock") {
1289 this->
schedule_([obj]() { obj->lock(); });
1291 }
else if (match.
method ==
"unlock") {
1292 this->
schedule_([obj]() { obj->unlock(); });
1294 }
else if (match.
method ==
"open") {
1295 this->
schedule_([obj]() { obj->open(); });
1305 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1322 if (this->
events_.count() == 0)
1328 if (obj->get_object_id() != match.
id)
1331 if (request->method() == HTTP_GET && match.
method.empty()) {
1333 auto *param = request->getParam(
"detail");
1334 if (param && param->value() ==
"all") {
1337 std::string data = this->
valve_json(obj, detail);
1338 request->send(200,
"application/json", data.c_str());
1342 auto call = obj->make_call();
1343 if (match.
method ==
"open") {
1344 call.set_command_open();
1345 }
else if (match.
method ==
"close") {
1346 call.set_command_close();
1347 }
else if (match.
method ==
"stop") {
1348 call.set_command_stop();
1349 }
else if (match.
method ==
"toggle") {
1350 call.set_command_toggle();
1351 }
else if (match.
method !=
"set") {
1356 auto traits = obj->get_traits();
1357 if (request->hasParam(
"position") && !traits.get_supports_position()) {
1362 if (request->hasParam(
"position")) {
1363 auto position = parse_number<float>(request->getParam(
"position")->value().c_str());
1395 #ifdef USE_ALARM_CONTROL_PANEL 1397 if (this->
events_.count() == 0)
1403 if (obj->get_object_id() != match.
id)
1406 if (request->method() == HTTP_GET && match.
method.empty()) {
1408 auto *param = request->getParam(
"detail");
1409 if (param && param->value() ==
"all") {
1413 request->send(200,
"application/json", data.c_str());
1417 auto call = obj->make_call();
1418 if (request->hasParam(
"code")) {
1419 call.set_code(request->getParam(
"code")->value().c_str());
1422 if (match.
method ==
"disarm") {
1424 }
else if (match.
method ==
"arm_away") {
1426 }
else if (match.
method ==
"arm_home") {
1428 }
else if (match.
method ==
"arm_night") {
1430 }
else if (match.
method ==
"arm_vacation") {
1431 call.arm_vacation();
1446 return json::build_json([
this, obj, value, start_config](JsonObject root) {
1448 set_json_icon_state_value(root, obj,
"alarm-control-panel-" + obj->
get_object_id(),
1468 if (obj->get_object_id() != match.
id)
1471 if (request->method() == HTTP_GET && match.
method.empty()) {
1473 auto *param = request->getParam(
"detail");
1474 if (param && param->value() ==
"all") {
1477 std::string data = this->
event_json(obj,
"", detail);
1478 request->send(200,
"application/json", data.c_str());
1485 return json::build_json([
this, obj, event_type, start_config](JsonObject root) {
1486 set_json_id(root, obj,
"event-" + obj->
get_object_id(), start_config);
1487 if (!event_type.empty()) {
1488 root[
"event_type"] = event_type;
1491 JsonArray event_types = root.createNestedArray(
"event_types");
1493 event_types.add(event_type);
1509 if (this->
events_.count() == 0)
1515 if (obj->get_object_id() != match.
id)
1518 if (request->method() == HTTP_GET && match.
method.empty()) {
1520 auto *param = request->getParam(
"detail");
1521 if (param && param->value() ==
"all") {
1524 std::string data = this->
update_json(obj, detail);
1525 request->send(200,
"application/json", data.c_str());
1529 if (match.
method !=
"install") {
1534 this->
schedule_([obj]()
mutable { obj->perform(); });
1542 set_json_id(root, obj,
"update-" + obj->
get_object_id(), start_config);
1544 switch (obj->
state) {
1546 root[
"state"] =
"NO UPDATE";
1549 root[
"state"] =
"UPDATE AVAILABLE";
1552 root[
"state"] =
"INSTALLING";
1555 root[
"state"] =
"UNKNOWN";
1575 if (request->url() ==
"/")
1578 #ifdef USE_WEBSERVER_CSS_INCLUDE 1579 if (request->url() ==
"/0.css")
1583 #ifdef USE_WEBSERVER_JS_INCLUDE 1584 if (request->url() ==
"/0.js")
1588 #ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS 1589 if (request->method() == HTTP_OPTIONS && request->hasHeader(HEADER_CORS_REQ_PNA)) {
1594 request->addInterestingHeader(HEADER_CORS_REQ_PNA);
1604 if (request->method() == HTTP_GET && match.
domain ==
"sensor")
1609 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"switch")
1614 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"button")
1618 #ifdef USE_BINARY_SENSOR 1619 if (request->method() == HTTP_GET && match.
domain ==
"binary_sensor")
1624 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"fan")
1629 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"light")
1633 #ifdef USE_TEXT_SENSOR 1634 if (request->method() == HTTP_GET && match.
domain ==
"text_sensor")
1639 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"cover")
1644 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"number")
1648 #ifdef USE_DATETIME_DATE 1649 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"date")
1653 #ifdef USE_DATETIME_TIME 1654 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"time")
1658 #ifdef USE_DATETIME_DATETIME 1659 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"datetime")
1664 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"text")
1669 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"select")
1674 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"climate")
1679 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"lock")
1684 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"valve")
1688 #ifdef USE_ALARM_CONTROL_PANEL 1689 if ((request->method() == HTTP_GET || request->method() == HTTP_POST) && match.
domain ==
"alarm_control_panel")
1694 if (request->method() == HTTP_GET && match.
domain ==
"event")
1699 if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
domain ==
"update")
1706 if (request->url() ==
"/") {
1711 #ifdef USE_WEBSERVER_CSS_INCLUDE 1712 if (request->url() ==
"/0.css") {
1718 #ifdef USE_WEBSERVER_JS_INCLUDE 1719 if (request->url() ==
"/0.js") {
1725 #ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS 1726 if (request->method() == HTTP_OPTIONS && request->hasHeader(HEADER_CORS_REQ_PNA)) {
1734 if (match.
domain ==
"sensor") {
1741 if (match.
domain ==
"switch") {
1748 if (match.
domain ==
"button") {
1754 #ifdef USE_BINARY_SENSOR 1755 if (match.
domain ==
"binary_sensor") {
1762 if (match.
domain ==
"fan") {
1769 if (match.
domain ==
"light") {
1775 #ifdef USE_TEXT_SENSOR 1776 if (match.
domain ==
"text_sensor") {
1783 if (match.
domain ==
"cover") {
1790 if (match.
domain ==
"number") {
1796 #ifdef USE_DATETIME_DATE 1797 if (match.
domain ==
"date") {
1803 #ifdef USE_DATETIME_TIME 1804 if (match.
domain ==
"time") {
1810 #ifdef USE_DATETIME_DATETIME 1811 if (match.
domain ==
"datetime") {
1818 if (match.
domain ==
"text") {
1825 if (match.
domain ==
"select") {
1832 if (match.
domain ==
"climate") {
1839 if (match.
domain ==
"lock") {
1847 if (match.
domain ==
"valve") {
1853 #ifdef USE_ALARM_CONTROL_PANEL 1854 if (match.
domain ==
"alarm_control_panel") {
1862 if (match.
domain ==
"update") {
1885 this->
defer(std::move(f));
Base class for all switches.
value_type const & value() const
bool state
The current on/off state of the fan.
const size_t ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE
ClimateSwingMode swing_mode
The active swing mode of the climate device.
float target_temperature_low
const std::vector< datetime::DateTimeEntity * > & get_datetimes()
void handle_pna_cors_request(AsyncWebServerRequest *request)
AlarmControlPanelState get_state() const
Get the state.
void handle_number_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a number request under '/number/<id>'.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
bool oscillating
The current oscillation state of the fan.
void set_interval(const std::string &name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
std::string number_json(number::Number *obj, float value, JsonDetail start_config)
Dump the number state with its value as a JSON string.
std::string sensor_json(sensor::Sensor *obj, float value, JsonDetail start_config)
Dump the sensor state with its value as a JSON string.
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.
void on_sensor_update(sensor::Sensor *obj, float state) override
bool is_on() const
Get the binary true/false state of these light color values.
Base class for all cover devices.
std::string value_accuracy_to_string(float value, int8_t accuracy_decimals)
Create a string from a value and an accuracy in decimals.
WebServer(web_server_base::WebServerBase *base)
void handleRequest(AsyncWebServerRequest *request) override
Override the web handler's handleRequest method.
TextMode get_mode() const
ClimatePreset
Enum for all preset modes.
void handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a time request under '/time/<id>'.
const std::vector< climate::Climate * > & get_climates()
float target_temperature
The target temperature of the climate device.
SemaphoreHandle_t to_schedule_lock_
std::string get_use_address()
Get the active network hostname.
void handle_binary_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a binary sensor request under '/binary_sensor/<id>'.
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.
LockState state
The current reported state of the lock.
std::string get_device_class()
Get the device class, using the manual override if set.
const std::vector< update::UpdateEntity * > & get_updates()
const std::vector< alarm_control_panel::AlarmControlPanel * > & get_alarm_control_panels()
bool is_fully_closed() const
Helper method to check if the valve is fully closed. Equivalent to comparing .position against 0...
const char * lock_state_to_string(LockState state)
void handle_select_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a select request under '/select/<id>'.
const std::vector< valve::Valve * > & get_valves()
void handle_text_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a text input request under '/text/<id>'.
CoverOperation current_operation
The current operation of the cover (idle, opening, closing).
std::map< EntityBase *, SortingComponents > sorting_entitys_
float position
The position of the valve from 0.0 (fully closed) to 1.0 (fully open).
void handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a event request under '/event<id>'.
void handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a update request under '/update/<id>'.
const LogString * climate_mode_to_string(ClimateMode mode)
Convert the given ClimateMode to a human-readable string.
virtual FanTraits get_traits()=0
std::set< std::string > get_event_types() const
void handle_valve_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a valve request under '/valve/<id>/<open/close/stop/set>'.
const UpdateState & state
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
const std::vector< event::Event * > & get_events()
bool get_supports_position() const
ClimateMode mode
The active mode of the climate device.
void on_lock_update(lock::Lock *obj) override
virtual bool assumed_state()
Return whether this switch uses an assumed state - i.e.
std::string latest_version
std::string current_version
const std::string & get_friendly_name() const
Get the friendly name of this Application set by pre_setup().
void setup() override
Setup the internal web server and register handlers.
float target_temperature_high
The maximum target temperature of the climate device, for climate devices with split target temperatu...
float current_temperature
The current temperature of the climate device, as reported from the integration.
const std::vector< fan::Fan * > & get_fans()
void on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool state) override
void handle_light_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a light request under '/light/<id>/</turn_on/turn_off/toggle>'.
bool isRequestHandlerTrivial() override
This web handle is not trivial.
void handle_lock_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a lock request under '/lock/<id>/</lock/unlock/open>'.
float target_temperature_high
void handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a button request under '/button/<id>/press'.
int get_max_length() const
Base-class for all text inputs.
bool supports_oscillation() const
Return if this fan supports oscillation.
void on_light_update(light::LightState *obj) override
virtual ValveTraits get_traits()=0
void on_event(event::Event *obj, const std::string &event_type) override
float tilt
The current tilt value of the cover from 0.0 to 1.0.
const std::vector< datetime::TimeEntity * > & get_times()
std::string get_object_id() const
uint32_t IRAM_ATTR HOT millis()
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.
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
ClimateSwingMode swing_mode
const size_t ESPHOME_WEBSERVER_JS_INCLUDE_SIZE
Internal helper struct that is used to parse incoming URLs.
optional< std::string > custom_fan_mode
The active custom fan mode of the climate device.
virtual CoverTraits get_traits()=0
void handle_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a sensor request under '/sensor/<id>'.
std::map< uint64_t, SortingGroup > sorting_groups_
const std::vector< lock::Lock * > & get_locks()
uint16_t get_port() const
void dump_config() override
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.
const size_t ESPHOME_WEBSERVER_INDEX_HTML_SIZE
std::string domain
The domain of the component, for example "sensor".
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.
std::string update_json(update::UpdateEntity *obj, JsonDetail start_config)
Dump the update state with its value as a JSON string.
void on_text_sensor_update(text_sensor::TextSensor *obj, const std::string &state) override
void add_handler(AsyncWebHandler *handler)
void set_css_include(const char *css_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
const std::vector< button::Button * > & get_buttons()
void handle_switch_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a switch request under '/switch/<id>/</turn_on/turn_off/toggle>'.
const LogString * alarm_control_panel_state_to_string(AlarmControlPanelState state)
Returns a string representation of the state.
std::vector< std::string > get_options() const
optional< ClimatePreset > preset
The active preset of the climate device.
const UpdateInfo & update_info
UrlMatch match_url(const std::string &url, bool only_domain=false)
const std::vector< switch_::Switch * > & get_switches()
Base-class for all numbers.
std::string str_sprintf(const char *fmt,...)
const char * cover_operation_to_str(CoverOperation op)
int speed
The current fan speed level.
void handle_alarm_control_panel_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a alarm_control_panel request under '/alarm_control_panel/<id>'.
void handle_css_request(AsyncWebServerRequest *request)
Handle included css request under '/0.css'.
bool valid
Whether this match is valid.
BedjetMode mode
BedJet operating mode.
bool is_fully_closed() const
Helper method to check if the cover is fully closed. Equivalent to comparing .position against 0...
void on_select_update(select::Select *obj, const std::string &state, size_t index) override
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
std::string get_unit_of_measurement()
Get the unit of measurement, using the manual override if set.
std::string time_json(datetime::TimeEntity *obj, JsonDetail start_config)
Dump the time state with its value as a JSON string.
const std::vector< text_sensor::TextSensor * > & get_text_sensors()
const LogString * climate_preset_to_string(ClimatePreset preset)
Convert the given PresetMode to a human-readable string.
int8_t get_target_temperature_accuracy_decimals() const
const std::vector< sensor::Sensor * > & get_sensors()
Application App
Global storage of Application pointer - only one Application can exist.
const std::vector< binary_sensor::BinarySensor * > & get_binary_sensors()
const std::vector< LightEffect * > & get_effects() const
Get all effects for this light state.
void handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a datetime request under '/datetime/<id>'.
bool get_supports_position() const
int8_t step_to_accuracy_decimals(float step)
Derive accuracy in decimals from an increment step.
std::string switch_json(switch_::Switch *obj, bool value, JsonDetail start_config)
Dump the switch state with its value as a JSON string.
std::string build_json(const json_build_t &f)
Build a JSON string with the provided json build function.
void begin(bool include_internal=false)
const std::string & get_name() const
Get the name of this Application set by pre_setup().
std::string light_json(light::LightState *obj, JsonDetail start_config)
Dump the light state as a JSON string.
void add_sorting_group(uint64_t group_id, const std::string &group_name, float weight)
void on_valve_update(valve::Valve *obj) override
static void dump_json(LightState &state, JsonObject root)
Dump the state of a light as JSON.
void add_entity_config(EntityBase *entity, float weight, uint64_t group)
const std::vector< text::Text * > & get_texts()
ClimateMode
Enum for all modes a climate device can be in.
void handle_index_request(AsyncWebServerRequest *request)
Handle an index request under '/'.
std::string valve_json(valve::Valve *obj, JsonDetail start_config)
Dump the valve state as a JSON string.
void on_time_update(datetime::TimeEntity *obj) override
void on_climate_update(climate::Climate *obj) override
const std::vector< cover::Cover * > & get_covers()
float get_setup_priority() const override
MQTT setup priority.
optional< std::string > custom_preset
The active custom preset mode of the climate device.
const LogString * climate_fan_mode_to_string(ClimateFanMode fan_mode)
Convert the given ClimateFanMode to a human-readable string.
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
void handle_fan_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a fan request under '/fan/<id>/</turn_on/turn_off/toggle>'.
std::string id
The id of the device that's being accessed, for example "living_room_fan".
const std::vector< light::LightState * > & get_lights()
void on_date_update(datetime::DateEntity *obj) override
std::string get_comment() const
Get the comment of this Application set by pre_setup().
std::string button_json(button::Button *obj, JsonDetail start_config)
Dump the button details with its value as a JSON string.
void on_cover_update(cover::Cover *obj) override
const char * valve_operation_to_str(ValveOperation op)
void handle_cover_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a cover request under '/cover/<id>/<open/close/stop/set>'.
void on_switch_update(switch_::Switch *obj, bool state) override
const char * css_include_
bool get_supports_tilt() const
void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) override
void setup_controller(bool include_internal=false)
void on_datetime_update(datetime::DateTimeEntity *obj) override
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::string datetime_json(datetime::DateTimeEntity *obj, JsonDetail start_config)
Dump the datetime state with its value as a JSON string.
Base-class for all selects.
void on_fan_update(fan::Fan *obj) override
web_server_base::WebServerBase * base_
Implementation of SPI Controller mode.
float get_min_value() const
void on_number_update(number::Number *obj, float state) override
Base class for all valve devices.
std::string fan_json(fan::Fan *obj, JsonDetail start_config)
Dump the fan state as a JSON string.
ValveOperation current_operation
The current operation of the valve (idle, opening, closing).
Base class for all binary_sensor-type classes.
LightColorValues remote_values
The remote color values reported to the frontend.
LockState
Enum for all states a lock can be in.
NumberMode get_mode() const
void handle_climate_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a climate request under '/climate/<id>'.
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
const std::vector< datetime::DateEntity * > & get_dates()
int get_min_length() const
const std::vector< select::Select * > & get_selects()
Base-class for all sensors.
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
bool canHandle(AsyncWebServerRequest *request) override
Override the web handler's canHandle method.
AsyncEventSourceResponse AsyncEventSourceClient
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.
ListEntitiesIterator entities_iterator_
std::deque< std::function< void()> > to_schedule_
const std::vector< number::Number * > & get_numbers()
float get_max_value() const
const LogString * climate_action_to_string(ClimateAction action)
Convert the given ClimateAction to a human-readable string.
void on_update(update::UpdateEntity *obj) override
void handle_text_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a text sensor request under '/text_sensor/<id>'.
void schedule_(std::function< void()> &&f)
std::string lock_json(lock::Lock *obj, lock::LockState value, JsonDetail start_config)
Dump the lock state with its value as a JSON string.
std::string get_pattern() const
float target_temperature_low
The minimum target temperature of the climate device, for climate devices with split target temperatu...
std::string climate_json(climate::Climate *obj, JsonDetail start_config)
Dump the climate details.
std::string method
The method that's being called, for example "turn_on".
void handle_date_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a date request under '/date/<id>'.
Base class for all locks.
ClimateAction action
The active state of the climate device.
ClimateDevice - This is the base class for all climate integrations.
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.
std::string cover_json(cover::Cover *obj, JsonDetail start_config)
Dump the cover state as a JSON string.
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.
const LogString * climate_swing_mode_to_string(ClimateSwingMode swing_mode)
Convert the given ClimateSwingMode to a human-readable string.