1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-09 06:42:20 +01:00

Add Captive Portal (#624)

* WIP: Captive Portal

* Updates

* Updates

* Lint

* Fixes
This commit is contained in:
Otto Winter
2019-06-09 17:03:51 +02:00
committed by GitHub
parent 8db6f3129c
commit 36f47ade70
38 changed files with 846 additions and 326 deletions

View File

@@ -6,13 +6,6 @@
#include "StreamString.h"
#ifdef ARDUINO_ARCH_ESP32
#include <Update.h>
#endif
#ifdef ARDUINO_ARCH_ESP8266
#include <Updater.h>
#endif
#include <cstdlib>
#include <esphome/components/logger/logger.h>
@@ -66,7 +59,7 @@ void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; }
void WebServer::setup() {
ESP_LOGCONFIG(TAG, "Setting up web server...");
this->server_ = new AsyncWebServer(this->port_);
this->base_->init();
this->events_.onConnect([this](AsyncEventSourceClient *client) {
// Configure reconnect timeout
@@ -114,91 +107,18 @@ void WebServer::setup() {
logger::global_logger->add_on_log_callback(
[this](int level, const char *tag, const char *message) { this->events_.send(message, "log", millis()); });
#endif
this->server_->addHandler(this);
this->server_->addHandler(&this->events_);
this->server_->begin();
this->base_->add_handler(&this->events_);
this->base_->add_handler(this);
this->base_->add_ota_handler();
this->set_interval(10000, [this]() { this->events_.send("", "ping", millis(), 30000); });
}
void WebServer::dump_config() {
ESP_LOGCONFIG(TAG, "Web Server:");
ESP_LOGCONFIG(TAG, " Address: %s:%u", network_get_address().c_str(), this->port_);
ESP_LOGCONFIG(TAG, " Address: %s:%u", network_get_address().c_str(), this->base_->get_port());
}
float WebServer::get_setup_priority() const { return setup_priority::WIFI - 1.0f; }
void WebServer::handle_update_request(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response;
if (!Update.hasError()) {
response = request->beginResponse(200, "text/plain", "Update Successful!");
} else {
StreamString ss;
ss.print("Update Failed: ");
Update.printError(ss);
response = request->beginResponse(200, "text/plain", ss);
}
response->addHeader("Connection", "close");
request->send(response);
}
void report_ota_error() {
StreamString ss;
Update.printError(ss);
ESP_LOGW(TAG, "OTA Update failed! Error: %s", ss.c_str());
}
void WebServer::handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data,
size_t len, bool final) {
bool success;
if (index == 0) {
ESP_LOGI(TAG, "OTA Update Start: %s", filename.c_str());
this->ota_read_length_ = 0;
#ifdef ARDUINO_ARCH_ESP8266
Update.runAsync(true);
success = Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
#endif
#ifdef ARDUINO_ARCH_ESP32
if (Update.isRunning())
Update.abort();
success = Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH);
#endif
if (!success) {
report_ota_error();
return;
}
} else if (Update.hasError()) {
// don't spam logs with errors if something failed at start
return;
}
success = Update.write(data, len) == len;
if (!success) {
report_ota_error();
return;
}
this->ota_read_length_ += len;
const uint32_t now = millis();
if (now - this->last_ota_progress_ > 1000) {
if (request->contentLength() != 0) {
float percentage = (this->ota_read_length_ * 100.0f) / request->contentLength();
ESP_LOGD(TAG, "OTA in progress: %0.1f%%", percentage);
} else {
ESP_LOGD(TAG, "OTA in progress: %u bytes read", this->ota_read_length_);
}
this->last_ota_progress_ = now;
}
if (final) {
if (Update.end(true)) {
ESP_LOGI(TAG, "OTA update successful!");
this->set_timeout(100, []() { App.safe_reboot(); });
} else {
report_ota_error();
}
}
}
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
AsyncResponseStream *stream = request->beginResponseStream("text/html");
std::string title = App.get_name() + " Web Server";
@@ -248,7 +168,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
stream->print(F("</tbody></table><p>See <a href=\"https://esphome.io/web-api/index.html\">ESPHome Web API</a> for "
"REST API documentation.</p>"
"<h2>OTA Update</h2><form method='POST' action=\"/update\" enctype=\"multipart/form-data\"><input "
"<h2>OTA Update</h2><form method=\"POST\" action=\"/update\" enctype=\"multipart/form-data\"><input "
"type=\"file\" name=\"update\"><input type=\"submit\" value=\"Update\"></form>"
"<h2>Debug Log</h2><pre id=\"log\"></pre>"
"<script src=\""));
@@ -531,9 +451,6 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) {
if (request->url() == "/")
return true;
if (request->url() == "/update" && request->method() == HTTP_POST)
return true;
UrlMatch match = match_url(request->url().c_str(), true);
if (!match.valid)
return false;
@@ -575,11 +492,6 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
return;
}
if (request->url() == "/update") {
this->handle_update_request(request);
return;
}
UrlMatch match = match_url(request->url().c_str());
#ifdef USE_SENSOR
if (match.domain == "sensor") {