15#if !defined(USE_ESP32) && defined(USE_ARDUINO)
16#include "StreamString.h"
37#ifdef USE_WATER_HEATER
44#ifdef USE_RADIO_FREQUENCY
48#ifdef USE_WEBSERVER_CAPTIVE
52#ifdef USE_WEBSERVER_LOCAL
53#if USE_WEBSERVER_VERSION == 2
55#elif USE_WEBSERVER_VERSION == 3
68[[maybe_unused]]
static ProgmemStr json_state_str(
const LogString *s) {
return reinterpret_cast<ProgmemStr>(s); }
71[[maybe_unused]]
static JsonString json_state_str(
const LogString *s) {
return linked(LOG_STR_ARG(s)); }
76template<
typename Call>
struct ActionEntry {
78 Call &(Call::*action)();
82template<
typename Call,
size_t N>
83static bool run_action(
const UrlMatch &match, Call &call,
const ActionEntry<Call> (&table)[N]) {
84 for (
const auto &entry : table) {
85 if (match.method_equals(
reinterpret_cast<ProgmemStr>(entry.name))) {
86 Call &(Call::*action)();
96[[maybe_unused]]
static void send_json(AsyncWebServerRequest *request, json::JsonBuilder &builder) {
97 auto data = builder.serialize();
98 request->send(200, ESPHOME_F(
"application/json"),
data.c_str());
107static UrlMatch match_url(
const char *url_ptr,
size_t url_len,
bool only_domain,
bool is_post =
false) {
112 if (url_len < 2 || url_ptr[0] !=
'/')
115 const char *p = url_ptr + 1;
116 const char *
end = url_ptr + url_len;
119 auto next_segment = [&
end](
const char *start) ->
const char * {
120 const char *slash = (
const char *) memchr(start,
'/',
end - start);
121 return slash ? slash + 1 :
nullptr;
125 auto make_ref = [&
end](
const char *start,
const char *next_start) -> StringRef {
126 return StringRef(start, (next_start ? next_start - 1 :
end) - start);
131 const char *s2 = next_segment(s1);
137 if (only_domain || s2 >=
end) {
138 match.domain = make_ref(s1, s2);
144 const char *s3 = next_segment(s2);
145 const char *s4 = s3 ? next_segment(s3) : nullptr;
147 StringRef seg2 = make_ref(s2, s3);
148 StringRef seg3 = s3 ? make_ref(s3, s4) : StringRef();
149 StringRef seg4 = s4 ? make_ref(s4,
nullptr) : StringRef();
152 if (seg2.empty() || (s3 && seg3.empty()) || (s4 && seg4.empty()))
167 match.device_name = seg2;
179 match.device_name = seg2;
188 match.domain = make_ref(s1, s2);
203 bool entity_has_device = (entity_device !=
nullptr);
206 if (url_has_device != entity_has_device) {
216 result.matched =
true;
222#if !defined(USE_ESP32) && defined(USE_ARDUINO)
226 DeferredEvent item(source, message_generator);
234 this->deferred_queue_.push_back(item);
241 de.message_generator_(
web_server_, de.source_, builder);
243 if (this->send(
message.c_str(),
"state") != DISCARDED) {
255 ESP_LOGW(TAG,
"Closing stuck EventSource connection after %" PRIu16
" failed sends",
274 if (this->
count() == 0)
291 if (this->send(
message.c_str(),
"state") == DISCARDED) {
304 this->send(
message, event,
id, reconnect);
311 return !this->empty();
335 es->onConnect([
this, es](AsyncEventSourceClient *client) { this->
on_client_connect_(es); });
339 es->handleRequest(request);
345 ws->
defer([ws, source]() {
351#ifdef USE_WEBSERVER_SORTING
354 JsonObject root = builder.
root();
355 root[ESPHOME_F(
"name")] = linked(group.second.name);
356 root[ESPHOME_F(
"sorting_weight")] = group.second.weight;
360 source->
try_send_nodefer(group_msg.c_str(), group_msg.size(),
"sorting_group");
372 this->remove(source);
378#ifdef USE_WEBSERVER_CAPTIVE
383#ifdef USE_WEBSERVER_CAPTIVE
393 JsonObject root = builder.
root();
398 root[ESPHOME_F(
"comment")] =
static_cast<const char *
>(comment_buffer);
399#if defined(USE_WEBSERVER_OTA_DISABLED) || !defined(USE_WEBSERVER_OTA)
400 root[ESPHOME_F(
"ota")] =
false;
402 root[ESPHOME_F(
"ota")] =
true;
405 root[ESPHOME_F(
"lang")] =
"en";
406 root[ESPHOME_F(
"uptime")] = uptime_seconds();
417 this, [](
void *self, uint8_t level,
const char *tag,
const char *
message,
size_t message_len) {
427#ifdef USE_WEBSERVER_CAPTIVE
441 auto uptime = uptime_seconds();
442 size_t len = buf_append_printf(buf,
sizeof(buf), 0,
"{\"uptime\":%" PRIu32
"}", uptime);
447 bool keep_looping = this->
events_.loop();
448#ifdef USE_WEBSERVER_CAPTIVE
462#ifdef USE_WEBSERVER_CAPTIVE
468 char ip_buf[network::IP_ADDRESS_BUFFER_SIZE];
470 ESP_LOGW(TAG,
"AP mode: captive DNS failed to start; open http://%s/ manually", ip.
str_to(ip_buf));
474 ESP_LOGI(TAG,
"AP mode: serving the web interface as captive portal at http://%s/", ip.
str_to(ip_buf));
483 char ip_buf[network::IP_ADDRESS_BUFFER_SIZE];
486 char location[7 + network::IP_ADDRESS_BUFFER_SIZE + 1];
487 buf_append_printf(location,
sizeof(location), 0,
"http://%s/", ip_buf);
488 request->redirect(location);
505 char addr_buf[network::USE_ADDRESS_BUFFER_SIZE];
513#ifdef USE_WEBSERVER_LOCAL
515 AsyncWebServerResponse *response = request->beginResponse(200, ESPHOME_F(
"text/html"), INDEX_GZ,
sizeof(INDEX_GZ));
516#ifdef USE_WEBSERVER_GZIP
517 response->addHeader(ESPHOME_F(
"Content-Encoding"), ESPHOME_F(
"gzip"));
519 response->addHeader(ESPHOME_F(
"Content-Encoding"), ESPHOME_F(
"br"));
521 request->send(response);
523#elif USE_WEBSERVER_VERSION >= 2
525 AsyncWebServerResponse *response = request->beginResponse(200, ESPHOME_F(
"text/html"), ESPHOME_WEBSERVER_INDEX_HTML,
528 request->send(response);
534static std::string get_request_header(AsyncWebServerRequest *request,
const char *name) {
537 optional<std::string> value = request->get_header(name);
538 return value.has_value() ? std::move(*value) :
std::string();
541 const AsyncWebHeader *header = request->getHeader(name);
542 return header !=
nullptr ? std::string(header->value().c_str()) :
std::string();
553 const size_t scheme_sep = origin.find(
"://");
554 if (scheme_sep != std::string::npos) {
555 const std::string host = get_request_header(request,
"Host");
557 const size_t authority = scheme_sep + 3;
558 if (!host.empty() && origin.size() - authority == host.size() &&
559 memcmp(origin.data() + authority, host.data(), host.size()) == 0)
563#ifdef USE_WEBSERVER_ALLOWED_ORIGINS
565 for (
const char *
const *it = this->
allowed_origins_; *it !=
nullptr; it++) {
566 const char *allowed_origin = *it;
568 if (allowed_origin[0] ==
'*' && allowed_origin[1] ==
'\0')
570 if (origin == allowed_origin)
577#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
579 const std::string origin = get_request_header(request,
"Origin");
585 AsyncWebServerResponse *response = request->beginResponse(200, ESPHOME_F(
""));
587 response->addHeader(ESPHOME_F(
"Access-Control-Allow-Origin"), origin.empty() ?
"*" : origin.c_str());
588 response->addHeader(ESPHOME_F(
"Access-Control-Allow-Private-Network"), ESPHOME_F(
"true"));
589 response->addHeader(ESPHOME_F(
"Private-Network-Access-Name"),
App.
get_name().
c_str());
590 char mac_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
592 request->send(response);
596#ifdef USE_WEBSERVER_CSS_INCLUDE
598 AsyncWebServerResponse *response = request->beginResponse(200, ESPHOME_F(
"text/css"), ESPHOME_WEBSERVER_CSS_INCLUDE,
600 response->addHeader(ESPHOME_F(
"Content-Encoding"), ESPHOME_F(
"gzip"));
601 request->send(response);
605#ifdef USE_WEBSERVER_JS_INCLUDE
607 AsyncWebServerResponse *response = request->beginResponse(
609 response->addHeader(ESPHOME_F(
"Content-Encoding"), ESPHOME_F(
"gzip"));
610 request->send(response);
617static void set_json_id(JsonObject root,
EntityBase *obj,
const char *prefix,
JsonDetail start_config) {
618 size_t prefix_len = strlen(prefix);
622 const char *device_name = device ? device->
get_name() :
nullptr;
623 size_t device_len = device_name ? strlen(device_name) : 0;
631 static constexpr size_t ID_BUF_SIZE =
632 ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1;
634 static constexpr size_t ID_BUF_SIZE = ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1;
636 char id_buf[ID_BUF_SIZE];
637 memcpy(id_buf, prefix, prefix_len);
639 char *p = id_buf + prefix_len;
643 memcpy(p, device_name, device_len);
649 const char *name = p;
652 root[ESPHOME_F(
"id")] =
static_cast<const char *
>(id_buf);
655 root[ESPHOME_F(
"domain")] = linked(prefix, prefix_len);
657 root[ESPHOME_F(
"name")] = name;
660 root[ESPHOME_F(
"name")] = linked(ram_name.
c_str(), ram_name.
size());
664 root[ESPHOME_F(
"device")] = linked(device_name, device_len);
667#ifdef USE_ENTITY_ICON
673 root[ESPHOME_F(
"is_disabled_by_default")] = is_disabled;
680static void set_json_value(JsonObject root, EntityBase *obj,
const char *prefix, T value,
JsonDetail start_config) {
681 set_json_id(root, obj, prefix, start_config);
682 root[ESPHOME_F(
"value")] =
value;
685template<
typename S,
typename T>
686static void set_json_icon_state_value(JsonObject root, EntityBase *obj,
const char *prefix, S
state, T value,
688 set_json_value(root, obj, prefix, value, start_config);
689 root[ESPHOME_F(
"state")] =
state;
693[[maybe_unused]]
static JsonDetail get_request_detail(AsyncWebServerRequest *request) {
698 if (!entity->
is_internal() || this->include_internal_)
699 this->
events_.deferrable_send_state(source,
false, generator);
707 if (!entity_match.matched)
710 if (entity_match.action_is_empty) {
711 auto detail = get_request_detail(request);
713 this->sensor_json_(obj, obj->state, detail, builder);
714 send_json(request, builder);
727 JsonObject root = builder.
root();
730 char buf[VALUE_ACCURACY_MAX_LEN];
731 const char *
state = std::isnan(value)
734 set_json_icon_state_value(root, obj,
"sensor",
state, value, start_config);
737 if (!uom_ref.empty())
738 root[ESPHOME_F(
"uom")] = linked(uom_ref);
743#ifdef USE_TEXT_SENSOR
750 if (!entity_match.matched)
753 if (entity_match.action_is_empty) {
754 auto detail = get_request_detail(request);
756 this->text_sensor_json_(obj, obj->
state, detail, builder);
757 send_json(request, builder);
773 JsonObject root = builder.
root();
776 const JsonString
state(value.c_str(), value.size());
777 set_json_icon_state_value(root, obj,
"text_sensor",
state,
state, start_config);
807 if (!entity_match.matched)
810 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
811 auto detail = get_request_detail(request);
813 this->switch_json_(obj, obj->
state, detail, builder);
814 send_json(request, builder);
829 this->
defer([obj, action]() { execute_switch_action(obj, action); });
845 JsonObject root = builder.
root();
847 set_json_icon_state_value(root, obj,
"switch", value ?
"ON" :
"OFF", value, start_config);
859 if (!entity_match.matched)
861 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
862 auto detail = get_request_detail(request);
864 this->button_json_(obj, detail, builder);
865 send_json(request, builder);
867 DEFER_ACTION(obj, obj->press());
881 JsonObject root = builder.
root();
883 set_json_id(root, obj,
"button", start_config);
890#ifdef USE_BINARY_SENSOR
897 if (!entity_match.matched)
900 if (entity_match.action_is_empty) {
901 auto detail = get_request_detail(request);
903 this->binary_sensor_json_(obj, obj->state, detail, builder);
904 send_json(request, builder);
920 JsonObject root = builder.
root();
922 set_json_icon_state_value(root, obj,
"binary_sensor", value ?
"ON" :
"OFF", value, start_config);
934 if (!entity_match.matched)
937 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
938 auto detail = get_request_detail(request);
940 this->fan_json_(obj, detail, builder);
941 send_json(request, builder);
943 DEFER_ACTION(obj, obj->toggle().perform());
948 if (!is_on && !is_off) {
952 auto call = is_on ? obj->turn_on() : obj->turn_off();
956 if (request->hasArg(ESPHOME_F(
"oscillation"))) {
957 auto speed = request->arg(ESPHOME_F(
"oscillation"));
961 call.set_oscillating(
true);
964 call.set_oscillating(
false);
967 call.set_oscillating(!obj->oscillating);
988 JsonObject root = builder.
root();
990 set_json_icon_state_value(root, obj,
"fan", obj->
state ?
"ON" :
"OFF", obj->
state, start_config);
992 if (traits.supports_speed()) {
993 root[ESPHOME_F(
"speed_level")] = obj->
speed;
994 root[ESPHOME_F(
"speed_count")] = traits.supported_speed_count();
1009 if (!entity_match.matched)
1012 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1013 auto detail = get_request_detail(request);
1015 this->light_json_(obj, detail, builder);
1016 send_json(request, builder);
1023 if (!is_on && !is_off) {
1045 request, ESPHOME_F(
"effect"),
call,
1049 DEFER_ACTION(
call,
call.perform());
1063 JsonObject root = builder.
root();
1069 JsonArray opt = root[ESPHOME_F(
"effects")].to<JsonArray>();
1070 opt.add(linked(
"None"));
1072 opt.add(linked(option->get_name()));
1084 if (!entity_match.matched)
1087 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1088 auto detail = get_request_detail(request);
1090 this->cover_json_(obj, detail, builder);
1091 send_json(request, builder);
1097 static constexpr ActionEntry<cover::CoverCall> ACTIONS[]
PROGMEM = {
1103 if (!run_action(match,
call, ACTIONS) && !match.
method_equals(ESPHOME_F(
"set"))) {
1109 if ((request->hasArg(ESPHOME_F(
"position")) && !traits.get_supports_position()) ||
1110 (request->hasArg(ESPHOME_F(
"tilt")) && !traits.get_supports_tilt())) {
1118 DEFER_ACTION(
call,
call.perform());
1131 JsonObject root = builder.
root();
1133 set_json_icon_state_value(root, obj,
"cover", linked(obj->
is_fully_closed() ?
"CLOSED" :
"OPEN"), obj->
position,
1138 root[ESPHOME_F(
"position")] = obj->
position;
1140 root[ESPHOME_F(
"tilt")] = obj->
tilt;
1151 for (
auto *obj :
App.get_numbers()) {
1153 if (!entity_match.matched)
1156 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1157 auto detail = get_request_detail(request);
1159 this->number_json_(obj, detail, builder);
1160 send_json(request, builder);
1171 DEFER_ACTION(
call,
call.perform());
1184 web_server->number_json_(obj,
DETAIL_ALL, builder);
1187 JsonObject root = builder.
root();
1194 char val_buf[VALUE_ACCURACY_MAX_LEN];
1195 char state_buf[VALUE_ACCURACY_MAX_LEN];
1196 JsonString val_str = linked(
"NaN");
1197 JsonString state_str = linked(
"NA");
1198 if (!std::isnan(value)) {
1201 val_str = JsonString(val_buf);
1202 state_str = JsonString(state_buf);
1204 set_json_icon_state_value(root, obj,
"number", state_str, val_str, start_config);
1211 if (!uom_ref.empty())
1212 root[ESPHOME_F(
"uom")] = linked(uom_ref);
1218#ifdef USE_DATETIME_DATE
1221 for (
auto *obj :
App.get_dates()) {
1223 if (!entity_match.matched)
1225 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1226 auto detail = get_request_detail(request);
1228 this->date_json_(obj, detail, builder);
1229 send_json(request, builder);
1239 const auto &value = request->arg(ESPHOME_F(
"value"));
1241 if (value.length() == 0) {
1245 call.set_date(value.c_str(), value.length());
1247 DEFER_ACTION(
call,
call.perform());
1261 JsonObject root = builder.
root();
1265 buf_append_printf(value,
sizeof(value), 0,
"%d-%02d-%02d", obj->
year, obj->
month, obj->
day);
1266 set_json_icon_state_value<const char *, const char *>(root, obj,
"date", value, value, start_config);
1273#ifdef USE_DATETIME_TIME
1276 for (
auto *obj :
App.get_times()) {
1278 if (!entity_match.matched)
1280 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1281 auto detail = get_request_detail(request);
1283 this->time_json_(obj, detail, builder);
1284 send_json(request, builder);
1294 const auto &value = request->arg(ESPHOME_F(
"value"));
1296 if (value.length() == 0) {
1300 call.set_time(value.c_str(), value.length());
1302 DEFER_ACTION(
call,
call.perform());
1315 JsonObject root = builder.
root();
1319 buf_append_printf(value,
sizeof(value), 0,
"%02d:%02d:%02d", obj->
hour, obj->
minute, obj->
second);
1320 set_json_icon_state_value<const char *, const char *>(root, obj,
"time", value, value, start_config);
1327#ifdef USE_DATETIME_DATETIME
1332 for (
auto *obj :
App.get_datetimes()) {
1334 if (!entity_match.matched)
1336 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1337 auto detail = get_request_detail(request);
1339 this->datetime_json_(obj, detail, builder);
1340 send_json(request, builder);
1350 const auto &value = request->arg(ESPHOME_F(
"value"));
1352 if (value.length() == 0) {
1356 call.set_datetime(value.c_str(), value.length());
1358 DEFER_ACTION(
call,
call.perform());
1371 JsonObject root = builder.
root();
1375 buf_append_printf(value,
sizeof(value), 0,
"%d-%02d-%02d %02d:%02d:%02d", obj->
year, obj->
month, obj->
day, obj->
hour,
1377 set_json_icon_state_value<const char *, const char *>(root, obj,
"datetime", value, value, start_config);
1387 for (
auto *obj :
App.get_texts()) {
1389 if (!entity_match.matched)
1392 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1393 auto detail = get_request_detail(request);
1395 this->text_json_(obj, obj->state, detail, builder);
1396 send_json(request, builder);
1406 request, ESPHOME_F(
"value"),
call,
1409 DEFER_ACTION(
call,
call.perform());
1424 JsonObject root = builder.
root();
1427 const JsonString copied_value(value.c_str(), value.size());
1431 set_json_icon_state_value(root, obj,
"text", password ? linked(
"********") : copied_value,
1432 password ? linked(
"") : copied_value, start_config);
1446 for (
auto *obj :
App.get_selects()) {
1448 if (!entity_match.matched)
1451 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1452 auto detail = get_request_detail(request);
1454 this->select_json_(obj, obj->
has_state() ? obj->current_option() :
StringRef(), detail, builder);
1455 send_json(request, builder);
1466 request, ESPHOME_F(
"option"),
call,
1469 DEFER_ACTION(
call,
call.perform());
1485 JsonObject root = builder.
root();
1487 const JsonString
state = linked(value);
1488 set_json_icon_state_value(root, obj,
"select",
state,
state, start_config);
1490 JsonArray opt = root[ESPHOME_F(
"option")].to<JsonArray>();
1492 opt.add(linked(option));
1502 for (
auto *obj :
App.get_climates()) {
1504 if (!entity_match.matched)
1507 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1508 auto detail = get_request_detail(request);
1510 this->climate_json_(obj, detail, builder);
1511 send_json(request, builder);
1524 request, ESPHOME_F(
"mode"),
call,
1528 &
decltype(
call)::set_fan_mode));
1531 &
decltype(
call)::set_swing_mode));
1534 &
decltype(
call)::set_preset));
1538 using ClimateCall =
decltype(
call);
1540 static_cast<ClimateCall &(ClimateCall::*)(
float)
>(&ClimateCall::set_target_temperature_high));
1542 static_cast<ClimateCall &(ClimateCall::*)(
float)
>(&ClimateCall::set_target_temperature_low));
1544 static_cast<ClimateCall &(ClimateCall::*)(
float)
>(&ClimateCall::set_target_temperature));
1546 DEFER_ACTION(
call,
call.perform());
1562 JsonObject root = builder.
root();
1563 set_json_id(root, obj,
"climate", start_config);
1566 int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals();
1567 char temp_buf[VALUE_ACCURACY_MAX_LEN];
1570 JsonArray opt = root[ESPHOME_F(
"modes")].to<JsonArray>();
1573 if (traits.get_supports_fan_modes()) {
1574 JsonArray opt = root[ESPHOME_F(
"fan_modes")].to<JsonArray>();
1579 if (!traits.get_supported_custom_fan_modes().empty()) {
1580 JsonArray opt = root[ESPHOME_F(
"custom_fan_modes")].to<JsonArray>();
1581 for (
auto const &
custom_fan_mode : traits.get_supported_custom_fan_modes())
1584 if (traits.get_supports_swing_modes()) {
1585 JsonArray opt = root[ESPHOME_F(
"swing_modes")].to<JsonArray>();
1586 for (
auto swing_mode : traits.get_supported_swing_modes())
1589 if (traits.get_supports_presets()) {
1590 JsonArray opt = root[ESPHOME_F(
"presets")].to<JsonArray>();
1594 if (!traits.get_supported_custom_presets().empty()) {
1595 JsonArray opt = root[ESPHOME_F(
"custom_presets")].to<JsonArray>();
1596 for (
auto const &
custom_preset : traits.get_supported_custom_presets())
1599 root[ESPHOME_F(
"max_temp")] =
1601 root[ESPHOME_F(
"min_temp")] =
1603 root[ESPHOME_F(
"step")] = traits.get_visual_target_temperature_step();
1604 root[ESPHOME_F(
"temperature_unit")] =
static_cast<uint8_t
>(traits.get_temperature_unit());
1608 bool has_state =
false;
1612 root[ESPHOME_F(
"state")] = root[ESPHOME_F(
"action")];
1615 if (traits.get_supports_fan_modes() && obj->
fan_mode.has_value()) {
1621 if (traits.get_supports_presets() && obj->
preset.has_value()) {
1624 if (!traits.get_supported_custom_presets().empty() && obj->
has_custom_preset()) {
1627 if (traits.get_supports_swing_modes()) {
1631 root[ESPHOME_F(
"current_temperature")] =
1643 root[ESPHOME_F(
"target_temperature_low")] =
1645 root[ESPHOME_F(
"target_temperature_high")] =
1648 root[ESPHOME_F(
"state")] =
1654 root[ESPHOME_F(
"target_temperature")] =
1657 root[ESPHOME_F(
"state")] = root[ESPHOME_F(
"target_temperature")];
1687 if (!entity_match.matched)
1690 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1691 auto detail = get_request_detail(request);
1693 this->lock_json_(obj, obj->
state, detail, builder);
1694 send_json(request, builder);
1709 this->
defer([obj, action]() { execute_lock_action(obj, action); });
1726 JsonObject root = builder.
root();
1740 if (!entity_match.matched)
1743 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1744 auto detail = get_request_detail(request);
1746 this->valve_json_(obj, detail, builder);
1747 send_json(request, builder);
1753 static constexpr ActionEntry<valve::ValveCall> ACTIONS[]
PROGMEM = {
1760 if (!run_action(match,
call, ACTIONS) && !match.
method_equals(ESPHOME_F(
"set"))) {
1765 auto traits = obj->get_traits();
1766 if (request->hasArg(ESPHOME_F(
"position")) && !traits.get_supports_position()) {
1773 DEFER_ACTION(
call,
call.perform());
1786 JsonObject root = builder.
root();
1788 set_json_icon_state_value(root, obj,
"valve", linked(obj->
is_fully_closed() ?
"CLOSED" :
"OPEN"), obj->
position,
1793 root[ESPHOME_F(
"position")] = obj->
position;
1800#ifdef USE_ALARM_CONTROL_PANEL
1807 if (!entity_match.matched)
1810 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1811 auto detail = get_request_detail(request);
1813 this->alarm_control_panel_json_(obj, obj->get_state(), detail, builder);
1814 send_json(request, builder);
1820 request, ESPHOME_F(
"code"),
call,
1822 const char *,
size_t)
>(&
decltype(
call)::set_code));
1824 static constexpr ActionEntry<alarm_control_panel::AlarmControlPanelCall> ACTIONS[]
PROGMEM = {
1832 if (!run_action(match,
call, ACTIONS)) {
1837 DEFER_ACTION(
call,
call.perform());
1858 JsonObject root = builder.
root();
1860 set_json_icon_state_value(root, obj,
"alarm_control_panel",
1861 json_state_str(alarm_control_panel_state_to_string(value)), value, start_config);
1868#ifdef USE_WATER_HEATER
1875 if (!entity_match.matched)
1878 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1879 auto detail = get_request_detail(request);
1881 this->water_heater_json_(obj, detail, builder);
1882 send_json(request, builder);
1895 request, ESPHOME_F(
"mode"), base_call,
1913 DEFER_ACTION(
call,
call.perform());
1929 JsonObject root = builder.
root();
1933 mode, start_config);
1938 JsonArray modes = root[ESPHOME_F(
"modes")].to<JsonArray>();
1939 for (
auto m : traits.get_supported_modes())
1941 root[ESPHOME_F(
"min_temp")] = traits.get_min_temperature();
1942 root[ESPHOME_F(
"max_temp")] = traits.get_max_temperature();
1943 root[ESPHOME_F(
"step")] = traits.get_target_temperature_step();
1944 root[ESPHOME_F(
"temperature_unit")] =
static_cast<uint8_t
>(traits.get_temperature_unit());
1948 if (traits.get_supports_current_temperature()) {
1950 if (!std::isnan(current))
1951 root[ESPHOME_F(
"current_temperature")] = current;
1954 if (traits.get_supports_two_point_target_temperature()) {
1957 if (!std::isnan(low))
1958 root[ESPHOME_F(
"target_temperature_low")] = low;
1959 if (!std::isnan(high))
1960 root[ESPHOME_F(
"target_temperature_high")] = high;
1963 if (!std::isnan(target))
1964 root[ESPHOME_F(
"target_temperature")] = target;
1967 if (traits.get_supports_away_mode()) {
1968 root[ESPHOME_F(
"away")] = obj->
is_away();
1972 root[ESPHOME_F(
"is_on")] = obj->
is_on();
1981 if (!entity_match.matched)
1984 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
1985 auto detail = get_request_detail(request);
1987 this->infrared_json_(obj, detail, builder);
1988 send_json(request, builder);
1997 if (!obj->has_transmitter()) {
1998 request->send(400, ESPHOME_F(
"text/plain"), ESPHOME_F(
"Device does not support transmission"));
2008 if (value.has_value()) {
2009 call.set_carrier_frequency(*value);
2016 if (value.has_value()) {
2017 call.set_repeat_count(*value);
2023 const auto &data_arg = request->arg(ESPHOME_F(
"data"));
2027 if (data_arg.length() == 0) {
2028 request->send(400, ESPHOME_F(
"text/plain"), ESPHOME_F(
"Missing or empty 'data' parameter"));
2036 this->
defer([call, encoded = std::string(data_arg.c_str(), data_arg.length())]()
mutable {
2037 call.set_raw_timings_base64url(encoded);
2053 JsonObject root = builder.
root();
2055 set_json_icon_state_value(root, obj,
"infrared",
"", 0, start_config);
2066#ifdef USE_RADIO_FREQUENCY
2070 if (!entity_match.matched)
2073 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
2074 auto detail = get_request_detail(request);
2076 this->radio_frequency_json_(obj, detail, builder);
2077 send_json(request, builder);
2087 request->send(400, ESPHOME_F(
"text/plain"), ESPHOME_F(
"Device does not support transmission"));
2096 if (value.has_value()) {
2097 call.set_frequency(*value);
2104 if (value.has_value()) {
2105 call.set_repeat_count(*value);
2111 const auto &data_arg = request->arg(ESPHOME_F(
"data"));
2115 if (data_arg.length() == 0) {
2116 request->send(400, ESPHOME_F(
"text/plain"), ESPHOME_F(
"Missing or empty 'data' parameter"));
2124 this->
defer([call, encoded = std::string(data_arg.c_str(), data_arg.length())]()
mutable {
2125 call.set_raw_timings_base64url(encoded);
2142 JsonObject root = builder.
root();
2144 set_json_icon_state_value(root, obj,
"radio_frequency",
"", 0, start_config);
2149 root[ESPHOME_F(
"supports_transmitter")] = bool(caps & radio_frequency::CAPABILITY_TRANSMITTER);
2150 root[ESPHOME_F(
"supports_receiver")] = bool(caps & radio_frequency::CAPABILITY_RECEIVER);
2151 if (traits.get_frequency_min_hz() != 0) {
2152 root[ESPHOME_F(
"frequency_min")] = traits.get_frequency_min_hz();
2153 root[ESPHOME_F(
"frequency_max")] = traits.get_frequency_max_hz();
2168 if (!entity_match.matched)
2172 if (entity_match.action_is_empty) {
2173 auto detail = get_request_detail(request);
2175 this->event_json_(obj,
StringRef(), detail, builder);
2176 send_json(request, builder);
2187 web_server->event_json_(event, get_event_type(event),
DETAIL_STATE, builder);
2192 web_server->event_json_(event, get_event_type(event),
DETAIL_ALL, builder);
2196 JsonObject root = builder.
root();
2198 set_json_id(root, obj,
"event", start_config);
2199 if (!event_type.
empty()) {
2200 root[ESPHOME_F(
"event_type")] = linked(event_type);
2203 JsonArray event_types = root[ESPHOME_F(
"event_types")].to<JsonArray>();
2205 event_types.add(linked(event_type));
2219 if (!entity_match.matched)
2222 if (request->method() == HTTP_GET && entity_match.action_is_empty) {
2223 auto detail = get_request_detail(request);
2225 this->update_json_(obj, detail, builder);
2226 send_json(request, builder);
2235 DEFER_ACTION(obj, obj->perform());
2251 JsonObject root = builder.
root();
2256 info.latest_version.c_str(), start_config);
2258 root[ESPHOME_F(
"current_version")] = info.current_version;
2259 root[ESPHOME_F(
"title")] = info.title;
2261 constexpr size_t max_summary_len = 256;
2262 root[ESPHOME_F(
"summary")] = JsonString(info.summary.c_str(), std::min(info.summary.size(), max_summary_len));
2263 root[ESPHOME_F(
"release_url")] = info.release_url;
2273 char url_buf[AsyncWebServerRequest::URL_BUF_SIZE];
2274 StringRef url = request->url_to(url_buf);
2276 const auto &url = request->url();
2278 const auto method = request->method();
2281 if (url == ESPHOME_F(
"/"))
2283#if !defined(USE_ESP32) && defined(USE_ARDUINO)
2284 if (url == ESPHOME_F(
"/events"))
2287#ifdef USE_WEBSERVER_CSS_INCLUDE
2288 if (url == ESPHOME_F(
"/0.css"))
2291#ifdef USE_WEBSERVER_JS_INCLUDE
2292 if (url == ESPHOME_F(
"/0.js"))
2296#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
2297 if (method == HTTP_OPTIONS && request->hasHeader(ESPHOME_F(
"Access-Control-Request-Private-Network")))
2307 bool is_get = method == HTTP_GET;
2308 bool is_post = method == HTTP_POST;
2309 bool is_get_or_post = is_get || is_post;
2311 if (!is_get_or_post)
2320#ifdef USE_BINARY_SENSOR
2324#ifdef USE_TEXT_SENSOR
2335 if (is_get_or_post) {
2360#ifdef USE_DATETIME_DATE
2364#ifdef USE_DATETIME_TIME
2368#ifdef USE_DATETIME_DATETIME
2392#ifdef USE_ALARM_CONTROL_PANEL
2400#ifdef USE_WATER_HEATER
2408#ifdef USE_RADIO_FREQUENCY
2418 char url_buf[AsyncWebServerRequest::URL_BUF_SIZE];
2419 StringRef url = request->url_to(url_buf);
2421 const auto &url = request->url();
2425 if (url == ESPHOME_F(
"/")) {
2430#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
2433 if (request->method() == HTTP_OPTIONS && request->hasHeader(ESPHOME_F(
"Access-Control-Request-Private-Network"))) {
2445#if !defined(USE_ESP32) && defined(USE_ARDUINO)
2446 if (url == ESPHOME_F(
"/events")) {
2447 this->
events_.add_new_client(
this, request);
2452#ifdef USE_WEBSERVER_CSS_INCLUDE
2453 if (url == ESPHOME_F(
"/0.css")) {
2459#ifdef USE_WEBSERVER_JS_INCLUDE
2460 if (url == ESPHOME_F(
"/0.js")) {
2468 UrlMatch match = match_url(url.
c_str(), url.
length(),
false, request->method() == HTTP_POST);
2490#ifdef USE_BINARY_SENSOR
2505#ifdef USE_TEXT_SENSOR
2520#ifdef USE_DATETIME_DATE
2525#ifdef USE_DATETIME_TIME
2530#ifdef USE_DATETIME_DATETIME
2560#ifdef USE_ALARM_CONTROL_PANEL
2561 else if (match.
domain_equals(ESPHOME_F(
"alarm_control_panel"))) {
2570#ifdef USE_WATER_HEATER
2580#ifdef USE_RADIO_FREQUENCY
2581 else if (match.
domain_equals(ESPHOME_F(
"radio_frequency"))) {
2587 ESP_LOGV(TAG,
"Request for unknown URL: %s", url.
c_str());
2588 request->send(404, ESPHOME_F(
"text/plain"), ESPHOME_F(
"Not Found"));
2595#ifdef USE_WEBSERVER_SORTING
2598 if (this->
sorting_groups_.contains(this->sorting_entitys_[entity].group_id)) {
2605#ifdef USE_WEBSERVER_SORTING
BedjetMode mode
BedJet operating mode.
const StringRef & get_name() const
Get the name of this Application set by pre_setup().
const StringRef & get_friendly_name() const
Get the friendly name of this Application set by pre_setup().
static constexpr size_t ESPHOME_COMMENT_SIZE_MAX
Maximum size of the comment buffer (including null terminator)
void get_comment_string(std::span< char, ESPHOME_COMMENT_SIZE_MAX > buffer)
Copy the comment string into the provided buffer.
void enable_loop_soon_any_context()
Thread and ISR-safe version of enable_loop() that can be called from any context.
void enable_loop()
Enable this component's loop.
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
void disable_loop()
Disable this component's loop.
void set_interval(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a const char* name.
void begin(bool include_internal=false)
ESPHOME_ALWAYS_INLINE void try_advance(size_t max_steps)
Run up to max_steps iteration steps; stops early when iteration completes or a callback refuses (that...
const ProgmemStringRef & get_name_progmem() const
The name as stored, for consumers that read flash themselves (e.g. API progmem fields).
ProgmemStringRef get_device_class_progmem() const
The device class as stored (in flash on ESP8266), for consumers that read flash themselves.
size_t write_name_to(char *buf, size_t buf_size) const
Copy the name into buf (null terminated), returns its length.
bool name_equals(const StringRef &other) const
ProgmemStringRef get_icon_progmem() const
The icon as stored (in flash on ESP8266), for consumers that read flash themselves.
bool is_disabled_by_default() const
StringRef get_unit_of_measurement_ref() const
Device * get_device() const
EntityCategory get_entity_category() const
constexpr const StringRef & ram_ref() const
The string is in RAM here, so it can be viewed directly.
StringRef is a reference to a string owned by something else.
constexpr const char * c_str() const
constexpr size_type length() const
constexpr bool empty() const
constexpr size_type size() const
AlarmControlPanelCall & arm_night()
AlarmControlPanelCall & disarm()
AlarmControlPanelCall & arm_away()
AlarmControlPanelCall & arm_home()
AlarmControlPanelCall & arm_vacation()
AlarmControlPanelCall make_call()
Make a AlarmControlPanelCall.
Base class for all binary_sensor-type classes.
This class is used to encode all control actions on a climate device.
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.
float current_humidity
The current humidity of the climate device, as reported from the integration.
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...
bool has_custom_preset() const
Check if a custom preset is currently active.
float current_temperature
The current temperature of the climate device, as reported from the integration.
ClimateAction action
The active state of the climate device.
StringRef get_custom_preset() const
Get the active custom preset (read-only access). Returns StringRef.
bool has_custom_fan_mode() const
Check if a custom fan mode is currently active.
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...
StringRef get_custom_fan_mode() const
Get the active custom fan mode (read-only access). Returns StringRef.
int8_t get_target_temperature_accuracy_decimals() const
CoverCall & set_command_toggle()
Set the command to toggle the cover.
CoverCall & set_command_open()
Set the command to open the cover.
CoverCall & set_command_close()
Set the command to close the cover.
CoverCall & set_command_stop()
Set the command to stop the cover.
CoverCall & set_command_stop_tilt()
Set the command to stop the cover tilt.
Base class for all cover devices.
CoverOperation current_operation
The current operation of the cover (idle, opening, closing).
CoverCall make_call()
Construct a new cover call used to control the cover.
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_is_assumed_state() const
bool get_supports_tilt() const
const EventTypes & get_event_types() const
Return the event types supported by this event.
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.
Infrared - Base class for infrared remote control implementations.
InfraredCall make_call()
Create a call object for transmitting.
uint32_t get_capability_flags() const
Capability flags as reported to the API and web server.
bool get_supports_transmitter() const
What the entity can do; platforms with their own hardware set these from their own setup(),...
bool get_supports_receiver() const
Builder class for creating JSON documents without lambdas.
SerializationBuffer serialize()
Serialize the JSON document to a SerializationBuffer (stack-first allocation) Uses 512-byte stack buf...
Buffer for JSON serialization that uses stack allocation for small payloads.
This class represents a requested change in a light state.
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 LightColorValues & get_reported_values() const
The values reported to the frontend: current_values while a light publishes intermediate states on an...
const ConstVector< LightEffect * > & get_effects() const
Get all effects for this light state.
Base class for all locks.
LockCall make_call()
Make a lock device control call, this is used to control the lock device, see the LockCall descriptio...
void lock()
Turn this lock on.
LockState state
The current reported state of the lock.
void unlock()
Turn this lock off.
void open()
Open (unlatch) this lock.
void add_log_callback(void *instance, void(*fn)(void *, uint8_t, const char *, const char *, size_t))
Register a log callback to receive log messages.
Base-class for all numbers.
float get_min_value() const
float get_max_value() const
NumberMode get_mode() const
RadioFrequency - Base class for radio frequency implementations.
RadioFrequencyTraits & get_traits()
Get the traits for this radio frequency implementation.
Base-class for all selects.
SelectCall make_call()
Instantiate a SelectCall object to modify this select component's state.
const SelectOptions & get_options() const
Base-class for all sensors.
float state
This member variable stores the last state that has passed through all filters.
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
Base class for all switches.
void toggle()
Toggle this switch.
void turn_on()
Turn this switch on.
void turn_off()
Turn this switch off.
bool state
The current reported state of the binary sensor.
virtual bool assumed_state()
Return whether this switch uses an assumed state - i.e.
Base-class for all text inputs.
TextCall make_call()
Instantiate a TextCall object to modify this text component's state.
TextMode get_mode() const
int get_max_length() const
int get_min_length() const
const char * get_pattern_c_str() const
const UpdateState & state
const UpdateInfo & update_info
ValveCall & set_command_close()
Set the command to close the valve.
ValveCall & set_command_toggle()
Set the command to toggle the valve.
ValveCall & set_command_stop()
Set the command to stop the valve.
ValveCall & set_command_open()
Set the command to open the valve.
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).
ValveCall make_call()
Construct a new valve call used to control the valve.
ValveOperation current_operation
The current operation of the valve (idle, opening, closing).
virtual ValveTraits get_traits()=0
bool get_supports_position() const
WaterHeaterCall & set_away(bool away)
WaterHeaterCall & set_target_temperature_high(float temperature)
WaterHeaterCall & set_mode(WaterHeaterMode mode)
WaterHeaterCall & set_target_temperature_low(float temperature)
WaterHeaterCall & set_on(bool on)
WaterHeaterCall & set_target_temperature(float temperature)
float get_target_temperature_low() const
float get_target_temperature() const
bool is_on() const
Check if the water heater is on.
float get_current_temperature() const
bool is_away() const
Check if away mode is currently active.
virtual WaterHeaterCallInternal make_call()=0
WaterHeaterMode get_mode() const
virtual WaterHeaterTraits get_traits()
float get_target_temperature_high() const
void process_deferred_queue_()
static constexpr uint16_t MAX_CONSECUTIVE_SEND_FAILURES
uint16_t consecutive_send_failures_
void deq_push_back_with_dedup_(void *source, message_generator_t *message_generator)
void try_send_nodefer(const char *message, size_t message_len, const char *event=nullptr, uint32_t id=0, uint32_t reconnect=0)
void deferrable_send_state(void *source, bool detail_all, message_generator_t *message_generator)
ListEntitiesIterator entities_iterator_
std::vector< DeferredEvent > deferred_queue_
void on_client_connect_(DeferredUpdateEventSource *source)
void try_send_nodefer(const char *message, size_t message_len, const char *event=nullptr, uint32_t id=0, uint32_t reconnect=0)
void add_new_client(WebServer *ws, AsyncWebServerRequest *request)
void deferrable_send_state(void *source, bool detail_all, message_generator_t *message_generator)
void on_client_disconnect_(DeferredUpdateEventSource *source)
bool loop()
Returns true if there are event sources remaining (including pending cleanup).
This class allows users to create a web server with their ESP nodes.
static void alarm_control_panel_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void setup() override
Setup the internal web server and register handlers.
void start_captive()
AP mode: DNS answers every name with the AP address and unknown URLs redirect to the interface.
static void text_sensor_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
json::SerializationBuffer get_config_json()
Return the webserver configuration as JSON.
std::map< EntityBase *, SortingComponents > sorting_entitys_
static void light_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void on_light_update(light::LightState *obj)
static void date_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void on_text_sensor_update(text_sensor::TextSensor *obj)
void on_lock_update(lock::Lock *obj)
void handle_select_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a select request under '/select/<id>'.
void on_date_update(datetime::DateEntity *obj)
static void event_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len)
static void cover_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handle_water_heater_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a water_heater request under '/water_heater/<id>/<mode/set>'.
bool isRequestHandlerTrivial() const override
This web handle is not trivial.
WebServer(web_server_base::WebServerBase *base)
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>'.
static void datetime_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void parse_light_param_uint_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret(T::*setter)(uint32_t), uint32_t scale=1)
static void sensor_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void dump_config() override
static void infrared_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void switch_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a button request under '/button/<id>/press'.
void on_update(update::UpdateEntity *obj)
void add_entity_config(EntityBase *entity, float weight, uint64_t group)
void handle_radio_frequency_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a radio frequency request under '/radio_frequency/<id>/transmit'.
static void update_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void parse_light_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret(T::*setter)(float), float scale=1.0f)
void handle_css_request(AsyncWebServerRequest *request)
Handle included css request under '/0.css'.
static void binary_sensor_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void water_heater_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void datetime_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void date_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void select_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void time_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void on_binary_sensor_update(binary_sensor::BinarySensor *obj)
void on_cover_update(cover::Cover *obj)
web_server_base::CaptiveDNS dns_
static void number_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void on_fan_update(fan::Fan *obj)
void add_sorting_info_(JsonObject &root, EntityBase *entity)
void handle_light_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a light request under '/light/<id>/</turn_on/turn_off/toggle>'.
static void update_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handle_text_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a text input request under '/text/<id>'.
void on_climate_update(climate::Climate *obj)
void handle_cover_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a cover request under '/cover/<id>/<open/close/stop/set>'.
void on_time_update(datetime::TimeEntity *obj)
static void event_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void switch_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void text_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void valve_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
web_server_base::WebServerBase * base_
void on_event(event::Event *obj)
void handle_lock_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a lock request under '/lock/<id>/</lock/unlock/open>'.
void on_water_heater_update(water_heater::WaterHeater *obj)
void on_number_update(number::Number *obj)
static void fan_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handle_text_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a text sensor request under '/text_sensor/<id>'.
static void select_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void parse_bool_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret(T::*setter)(bool))
bool is_request_origin_allowed_(AsyncWebServerRequest *request, const std::string &origin)
Check whether the given request Origin is permitted.
void handle_date_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a date request under '/date/<id>'.
void handle_infrared_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle an infrared request under '/infrared/<id>/transmit'.
void handle_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a sensor request under '/sensor/<id>'.
void handle_number_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a number request under '/number/<id>'.
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 on_select_update(select::Select *obj)
void on_sensor_update(sensor::Sensor *obj)
static void text_sensor_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void radio_frequency_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void time_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handleRequest(AsyncWebServerRequest *request) override
Override the web handler's handleRequest method.
void handle_fan_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a fan request under '/fan/<id>/</turn_on/turn_off/toggle>'.
static void button_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void parse_cstr_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret(T::*setter)(const char *, size_t))
static void alarm_control_panel_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void number_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void on_switch_update(switch_::Switch *obj)
static void light_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
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 void lock_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a time request under '/time/<id>'.
std::map< uint64_t, SortingGroup > sorting_groups_
static void fan_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
bool canHandle(AsyncWebServerRequest *request) const override
Override the web handler's canHandle method.
void on_valve_update(valve::Valve *obj)
static void water_heater_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void on_datetime_update(datetime::DateTimeEntity *obj)
void send_state_event_(T *obj, message_generator_t *generator)
void handle_pna_cors_request(AsyncWebServerRequest *request)
void on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj)
void handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a datetime request under '/datetime/<id>'.
void on_text_update(text::Text *obj)
void handle_alarm_control_panel_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a alarm_control_panel request under '/alarm_control_panel/<id>'.
const char *const * allowed_origins_
float get_setup_priority() const override
MQTT setup priority.
void handle_not_found_(AsyncWebServerRequest *request)
static void text_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void sensor_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void parse_num_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret(T::*setter)(NumT))
static void climate_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a update request under '/update/<id>'.
static void lock_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void add_sorting_group(uint64_t group_id, const std::string &group_name, float weight)
static void valve_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void cover_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void binary_sensor_all_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
static void climate_state_json_generator(WebServer *web_server, void *source, json::JsonBuilder &builder)
void handle_climate_request(AsyncWebServerRequest *request, const UrlMatch &match)
Handle a climate request under '/climate/<id>'.
void loop()
Answer one pending query; call from the owner's loop() while running.
bool start(const network::IPAddress &ip)
Returns false when the DNS server could not start; nothing is kept, so is_running() stays false.
void add_handler(AsyncWebHandler *handler)
AsyncWebServer * get_server() const
uint16_t get_port() const
network::IPAddress wifi_soft_ap_ip()
ClimateSwingMode swing_mode
struct @66::@67 __attribute__
Wake the main loop task from an ISR. ISR-safe.
const LogString * message
const LogString * climate_action_to_string(ClimateAction action)
Convert the given ClimateAction to a human-readable string.
@ CLIMATE_SUPPORTS_CURRENT_HUMIDITY
@ CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
@ CLIMATE_SUPPORTS_CURRENT_TEMPERATURE
@ CLIMATE_SUPPORTS_ACTION
@ CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE
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 NOTE: If adding values, update ClimatePresetMask in climate_traits....
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.
ClimateFanMode
NOTE: If adding values, update ClimateFanModeMask in climate_traits.h to use the new last value.
const LogString * cover_operation_to_str(CoverOperation op)
JsonString linked(const char *s)
const LogString * lock_state_to_string(LockState state)
LockState
Enum for all states a lock can be in.
std::span< const uint8_t > data
const char * get_use_address_to(std::span< char, USE_ADDRESS_BUFFER_SIZE > buf)
Get the active network address for logging.
value[LAYOUT.day_index()]
const LogString * update_state_to_string(UpdateState state)
const LogString * valve_operation_to_str(ValveOperation op)
@ WATER_HEATER_SUPPORTS_ON_OFF
The water heater can be turned on/off.
const LogString * water_heater_mode_to_string(WaterHeaterMode mode)
Convert the given WaterHeaterMode to a human-readable string for logging.
ESPHOME_LOG_TAG(TAG, "web_server.ota")
WebServer * global_web_server
constexpr size_t LOG_EVENT_MAX_LEN
constexpr uint8_t INDEX_GZ[] PROGMEM
void(WebServer *, void *, json::JsonBuilder &) message_generator_t
WiFiComponent * global_wifi_component
size_t value_accuracy_to_buf(std::span< char, VALUE_ACCURACY_MAX_LEN > buf, float value, int8_t accuracy_decimals)
Format value with accuracy to buffer, returns chars written (excluding null)
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
void progmem_memcpy(void *dst, const void *src, size_t len)
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
int8_t step_to_accuracy_decimals(float step)
Derive accuracy in decimals from an increment step.
const char * get_mac_address_pretty_into_buffer(std::span< char, MAC_ADDRESS_PRETTY_BUFFER_SIZE > buf)
Get the device MAC address into the given buffer, in colon-separated uppercase hex notation.
size_t value_accuracy_with_uom_to_buf(std::span< char, VALUE_ACCURACY_MAX_LEN > buf, float value, int8_t accuracy_decimals, StringRef unit_of_measurement)
Format value with accuracy and UOM to buffer, returns chars written (excluding null)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
const __FlashStringHelper * ProgmemStr
char * str_to(char *buf) const
Result of matching a URL against an entity.
Internal helper struct that is used to parse incoming URLs.
StringRef device_name
Device name within URL, empty for main device.
bool valid
Whether this match is valid.
EntityMatchResult match_entity(EntityBase *entity) const
Match entity by name; internal entities match only if include_internal is set Returns EntityMatchResu...
StringRef method
Method within URL, for example "turn_on".
bool domain_equals(const char *str) const
bool method_equals(const char *str) const
bool include_internal
Whether internal entities may match, the web server's include_internal.
const size_t ESPHOME_WEBSERVER_INDEX_HTML_SIZE
const size_t ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE
const size_t ESPHOME_WEBSERVER_JS_INCLUDE_SIZE