ESPHome 2025.9.0
Loading...
Searching...
No Matches
captive_portal.cpp
Go to the documentation of this file.
1#include "captive_portal.h"
2#ifdef USE_CAPTIVE_PORTAL
3#include "esphome/core/log.h"
6#include "captive_index.h"
7
8namespace esphome {
9namespace captive_portal {
10
11static const char *const TAG = "captive_portal";
12
13void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
14 AsyncResponseStream *stream = request->beginResponseStream(F("application/json"));
15 stream->addHeader(F("cache-control"), F("public, max-age=0, must-revalidate"));
16#ifdef USE_ESP8266
17 stream->print(F("{\"mac\":\""));
18 stream->print(get_mac_address_pretty().c_str());
19 stream->print(F("\",\"name\":\""));
20 stream->print(App.get_name().c_str());
21 stream->print(F("\",\"aps\":[{}"));
22#else
23 stream->printf(R"({"mac":"%s","name":"%s","aps":[{})", get_mac_address_pretty().c_str(), App.get_name().c_str());
24#endif
25
26 for (auto &scan : wifi::global_wifi_component->get_scan_result()) {
27 if (scan.get_is_hidden())
28 continue;
29
30 // Assumes no " in ssid, possible unicode isses?
31#ifdef USE_ESP8266
32 stream->print(F(",{\"ssid\":\""));
33 stream->print(scan.get_ssid().c_str());
34 stream->print(F("\",\"rssi\":"));
35 stream->print(scan.get_rssi());
36 stream->print(F(",\"lock\":"));
37 stream->print(scan.get_with_auth());
38 stream->print(F("}"));
39#else
40 stream->printf(R"(,{"ssid":"%s","rssi":%d,"lock":%d})", scan.get_ssid().c_str(), scan.get_rssi(),
41 scan.get_with_auth());
42#endif
43 }
44 stream->print(F("]}"));
45 request->send(stream);
46}
47void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
48 std::string ssid = request->arg("ssid").c_str();
49 std::string psk = request->arg("psk").c_str();
50 ESP_LOGI(TAG, "Requested WiFi Settings Change:");
51 ESP_LOGI(TAG, " SSID='%s'", ssid.c_str());
52 ESP_LOGI(TAG, " Password=" LOG_SECRET("'%s'"), psk.c_str());
55 request->redirect(F("/?save"));
56}
57
59#ifndef USE_ARDUINO
60 // No DNS server needed for non-Arduino frameworks
61 this->disable_loop();
62#endif
63}
65 this->base_->init();
66 if (!this->initialized_) {
67 this->base_->add_handler(this);
68 }
69
70#ifdef USE_ARDUINO
71 this->dns_server_ = make_unique<DNSServer>();
72 this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
74 this->dns_server_->start(53, F("*"), ip);
75 // Re-enable loop() when DNS server is started
76 this->enable_loop();
77#endif
78
79 this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {
80 if (!this->active_ || req->host().c_str() == wifi::global_wifi_component->wifi_soft_ap_ip().str()) {
81 req->send(404, F("text/html"), F("File not found"));
82 return;
83 }
84
85#ifdef USE_ESP8266
86 String url = F("http://");
88#else
89 auto url = "http://" + wifi::global_wifi_component->wifi_soft_ap_ip().str();
90#endif
91 req->redirect(url.c_str());
92 });
93
94 this->initialized_ = true;
95 this->active_ = true;
96}
97
98void CaptivePortal::handleRequest(AsyncWebServerRequest *req) {
99 if (req->url() == F("/")) {
100#ifndef USE_ESP8266
101 auto *response = req->beginResponse(200, F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
102#else
103 auto *response = req->beginResponse_P(200, F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
104#endif
105 response->addHeader(F("Content-Encoding"), F("gzip"));
106 req->send(response);
107 return;
108 } else if (req->url() == F("/config.json")) {
109 this->handle_config(req);
110 return;
111 } else if (req->url() == F("/wifisave")) {
112 this->handle_wifisave(req);
113 return;
114 }
115}
116
119 // Before WiFi
120 return setup_priority::WIFI + 1.0f;
121}
122void CaptivePortal::dump_config() { ESP_LOGCONFIG(TAG, "Captive Portal:"); }
123
124CaptivePortal *global_captive_portal = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
125
126} // namespace captive_portal
127} // namespace esphome
128#endif
const std::string & get_name() const
Get the name of this Application set by pre_setup().
void enable_loop()
Enable this component's loop.
void disable_loop()
Disable this component's loop.
std::unique_ptr< DNSServer > dns_server_
CaptivePortal(web_server_base::WebServerBase *base)
void handle_config(AsyncWebServerRequest *request)
web_server_base::WebServerBase * base_
void handleRequest(AsyncWebServerRequest *req) override
void handle_wifisave(AsyncWebServerRequest *request)
std::shared_ptr< AsyncWebServer > get_server() const
void add_handler(AsyncWebHandler *handler)
void save_wifi_sta(const std::string &ssid, const std::string &password)
CaptivePortal * global_captive_portal
WiFiComponent * global_wifi_component
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
Definition helpers.cpp:598
Application App
Global storage of Application pointer - only one Application can exist.
std::string str() const
Definition ip_address.h:52