ESPHome  2023.5.5
captive_portal.cpp
Go to the documentation of this file.
1 #ifdef USE_ARDUINO
2 
3 #include "captive_portal.h"
4 #include "esphome/core/log.h"
7 #include "captive_index.h"
8 
9 namespace esphome {
10 namespace captive_portal {
11 
12 static const char *const TAG = "captive_portal";
13 
14 void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
15  AsyncResponseStream *stream = request->beginResponseStream("application/json");
16  stream->addHeader("cache-control", "public, max-age=0, must-revalidate");
17  stream->printf(R"({"name":"%s","aps":[{})", App.get_name().c_str());
18 
19  for (auto &scan : wifi::global_wifi_component->get_scan_result()) {
20  if (scan.get_is_hidden())
21  continue;
22 
23  // Assumes no " in ssid, possible unicode isses?
24  stream->printf(R"(,{"ssid":"%s","rssi":%d,"lock":%d})", scan.get_ssid().c_str(), scan.get_rssi(),
25  scan.get_with_auth());
26  }
27  stream->print(F("]}"));
28  request->send(stream);
29 }
30 void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
31  std::string ssid = request->arg("ssid").c_str();
32  std::string psk = request->arg("psk").c_str();
33  ESP_LOGI(TAG, "Captive Portal Requested WiFi Settings Change:");
34  ESP_LOGI(TAG, " SSID='%s'", ssid.c_str());
35  ESP_LOGI(TAG, " Password=" LOG_SECRET("'%s'"), psk.c_str());
38  request->redirect("/?save");
39 }
40 
43  this->base_->init();
44  if (!this->initialized_) {
45  this->base_->add_handler(this);
46  this->base_->add_ota_handler();
47  }
48 
49  this->dns_server_ = make_unique<DNSServer>();
50  this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
52  this->dns_server_->start(53, "*", (uint32_t) ip);
53 
54  this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {
55  if (!this->active_ || req->host().c_str() == wifi::global_wifi_component->wifi_soft_ap_ip().str()) {
56  req->send(404, "text/html", "File not found");
57  return;
58  }
59 
60  auto url = "http://" + wifi::global_wifi_component->wifi_soft_ap_ip().str();
61  req->redirect(url.c_str());
62  });
63 
64  this->initialized_ = true;
65  this->active_ = true;
66 }
67 
68 void CaptivePortal::handleRequest(AsyncWebServerRequest *req) {
69  if (req->url() == "/") {
70  AsyncWebServerResponse *response = req->beginResponse_P(200, "text/html", INDEX_GZ, sizeof(INDEX_GZ));
71  response->addHeader("Content-Encoding", "gzip");
72  req->send(response);
73  return;
74  } else if (req->url() == "/config.json") {
75  this->handle_config(req);
76  return;
77  } else if (req->url() == "/wifisave") {
78  this->handle_wifisave(req);
79  return;
80  }
81 }
82 
85  // Before WiFi
86  return setup_priority::WIFI + 1.0f;
87 }
88 void CaptivePortal::dump_config() { ESP_LOGCONFIG(TAG, "Captive Portal:"); }
89 
90 CaptivePortal *global_captive_portal = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
91 
92 } // namespace captive_portal
93 } // namespace esphome
94 
95 #endif // USE_ARDUINO
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:28
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:143
Definition: a4988.cpp:4
std::shared_ptr< AsyncWebServer > get_server() const
float get_setup_priority() const override
void handle_wifisave(AsyncWebServerRequest *request)