ESPHome  2024.4.1
captive_portal.cpp
Go to the documentation of this file.
1 #include "captive_portal.h"
2 #include "esphome/core/log.h"
5 #include "captive_index.h"
6 
7 namespace esphome {
8 namespace captive_portal {
9 
10 static const char *const TAG = "captive_portal";
11 
12 void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
13  AsyncResponseStream *stream = request->beginResponseStream("application/json");
14  stream->addHeader("cache-control", "public, max-age=0, must-revalidate");
15  stream->printf(R"({"mac":"%s","name":"%s","aps":[{})", get_mac_address_pretty().c_str(), App.get_name().c_str());
16 
17  for (auto &scan : wifi::global_wifi_component->get_scan_result()) {
18  if (scan.get_is_hidden())
19  continue;
20 
21  // Assumes no " in ssid, possible unicode isses?
22  stream->printf(R"(,{"ssid":"%s","rssi":%d,"lock":%d})", scan.get_ssid().c_str(), scan.get_rssi(),
23  scan.get_with_auth());
24  }
25  stream->print(F("]}"));
26  request->send(stream);
27 }
28 void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
29  std::string ssid = request->arg("ssid").c_str();
30  std::string psk = request->arg("psk").c_str();
31  ESP_LOGI(TAG, "Captive Portal Requested WiFi Settings Change:");
32  ESP_LOGI(TAG, " SSID='%s'", ssid.c_str());
33  ESP_LOGI(TAG, " Password=" LOG_SECRET("'%s'"), psk.c_str());
36  request->redirect("/?save");
37 }
38 
41  this->base_->init();
42  if (!this->initialized_) {
43  this->base_->add_handler(this);
44  this->base_->add_ota_handler();
45  }
46 
47 #ifdef USE_ARDUINO
48  this->dns_server_ = make_unique<DNSServer>();
49  this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
51  this->dns_server_->start(53, "*", ip);
52 #endif
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  auto *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
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:120
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:174
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
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:592
float get_setup_priority() const override
void handle_wifisave(AsyncWebServerRequest *request)