ESPHome  2024.9.0
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 
8 namespace esphome {
9 namespace captive_portal {
10 
11 static const char *const TAG = "captive_portal";
12 
13 void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
14  AsyncResponseStream *stream = request->beginResponseStream("application/json");
15  stream->addHeader("cache-control", "public, max-age=0, must-revalidate");
16  stream->printf(R"({"mac":"%s","name":"%s","aps":[{})", get_mac_address_pretty().c_str(), App.get_name().c_str());
17 
18  for (auto &scan : wifi::global_wifi_component->get_scan_result()) {
19  if (scan.get_is_hidden())
20  continue;
21 
22  // Assumes no " in ssid, possible unicode isses?
23  stream->printf(R"(,{"ssid":"%s","rssi":%d,"lock":%d})", scan.get_ssid().c_str(), scan.get_rssi(),
24  scan.get_with_auth());
25  }
26  stream->print(F("]}"));
27  request->send(stream);
28 }
29 void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
30  std::string ssid = request->arg("ssid").c_str();
31  std::string psk = request->arg("psk").c_str();
32  ESP_LOGI(TAG, "Captive Portal Requested WiFi Settings Change:");
33  ESP_LOGI(TAG, " SSID='%s'", ssid.c_str());
34  ESP_LOGI(TAG, " Password=" LOG_SECRET("'%s'"), psk.c_str());
37  request->redirect("/?save");
38 }
39 
42  this->base_->init();
43  if (!this->initialized_) {
44  this->base_->add_handler(this);
45  this->base_->add_ota_handler();
46  }
47 
48 #ifdef USE_ARDUINO
49  this->dns_server_ = make_unique<DNSServer>();
50  this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
52  this->dns_server_->start(53, "*", ip);
53 #endif
54 
55  this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {
56  if (!this->active_ || req->host().c_str() == wifi::global_wifi_component->wifi_soft_ap_ip().str()) {
57  req->send(404, "text/html", "File not found");
58  return;
59  }
60 
61  auto url = "http://" + wifi::global_wifi_component->wifi_soft_ap_ip().str();
62  req->redirect(url.c_str());
63  });
64 
65  this->initialized_ = true;
66  this->active_ = true;
67 }
68 
69 void CaptivePortal::handleRequest(AsyncWebServerRequest *req) {
70  if (req->url() == "/") {
71  auto *response = req->beginResponse_P(200, "text/html", INDEX_GZ, sizeof(INDEX_GZ));
72  response->addHeader("Content-Encoding", "gzip");
73  req->send(response);
74  return;
75  } else if (req->url() == "/config.json") {
76  this->handle_config(req);
77  return;
78  } else if (req->url() == "/wifisave") {
79  this->handle_wifisave(req);
80  return;
81  }
82 }
83 
86  // Before WiFi
87  return setup_priority::WIFI + 1.0f;
88 }
89 void CaptivePortal::dump_config() { ESP_LOGCONFIG(TAG, "Captive Portal:"); }
90 
91 CaptivePortal *global_captive_portal = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
92 
93 } // namespace captive_portal
94 } // namespace esphome
95 #endif
CaptivePortal(web_server_base::WebServerBase *base)
std::unique_ptr< DNSServer > dns_server_
void handleRequest(AsyncWebServerRequest *req) override
void save_wifi_sta(const std::string &ssid, const std::string &password)
std::string str() const
Definition: ip_address.h:122
web_server_base::WebServerBase * base_
CaptivePortal * global_captive_portal
void add_handler(AsyncWebHandler *handler)
void handle_config(AsyncWebServerRequest *request)
Application App
Global storage of Application pointer - only one Application can exist.
WiFiComponent * global_wifi_component
const std::string & get_name() const
Get the name of this Application set by pre_setup().
Definition: application.h:202
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
std::shared_ptr< AsyncWebServer > get_server() const
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
Definition: helpers.cpp:693
float get_setup_priority() const override
void handle_wifisave(AsyncWebServerRequest *request)