diff --git a/esphome/components/fujitsu_general/fujitsu_general.cpp b/esphome/components/fujitsu_general/fujitsu_general.cpp
index 291af8c8cd..6c7adebfea 100644
--- a/esphome/components/fujitsu_general/fujitsu_general.cpp
+++ b/esphome/components/fujitsu_general/fujitsu_general.cpp
@@ -151,11 +151,13 @@ void FujitsuGeneralClimate::transmit_state() {
case climate::CLIMATE_FAN_LOW:
SET_NIBBLE(remote_state, FUJITSU_GENERAL_FAN_NIBBLE, FUJITSU_GENERAL_FAN_LOW);
break;
+ case climate::CLIMATE_FAN_QUIET:
+ SET_NIBBLE(remote_state, FUJITSU_GENERAL_FAN_NIBBLE, FUJITSU_GENERAL_FAN_SILENT);
+ break;
case climate::CLIMATE_FAN_AUTO:
default:
SET_NIBBLE(remote_state, FUJITSU_GENERAL_FAN_NIBBLE, FUJITSU_GENERAL_FAN_AUTO);
break;
- // TODO Quiet / Silent
}
// Set swing
@@ -345,8 +347,9 @@ bool FujitsuGeneralClimate::on_receive(remote_base::RemoteReceiveData data) {
const uint8_t recv_fan_mode = GET_NIBBLE(recv_message, FUJITSU_GENERAL_FAN_NIBBLE);
ESP_LOGV(TAG, "Received fan mode %X", recv_fan_mode);
switch (recv_fan_mode) {
- // TODO No Quiet / Silent in ESPH
case FUJITSU_GENERAL_FAN_SILENT:
+ this->fan_mode = climate::CLIMATE_FAN_QUIET;
+ break;
case FUJITSU_GENERAL_FAN_LOW:
this->fan_mode = climate::CLIMATE_FAN_LOW;
break;
diff --git a/esphome/components/fujitsu_general/fujitsu_general.h b/esphome/components/fujitsu_general/fujitsu_general.h
index ee83ae9d19..d7d01bf6f3 100644
--- a/esphome/components/fujitsu_general/fujitsu_general.h
+++ b/esphome/components/fujitsu_general/fujitsu_general.h
@@ -52,7 +52,7 @@ class FujitsuGeneralClimate : public climate_ir::ClimateIR {
FujitsuGeneralClimate()
: ClimateIR(FUJITSU_GENERAL_TEMP_MIN, FUJITSU_GENERAL_TEMP_MAX, 1.0f, true, true,
{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM,
- climate::CLIMATE_FAN_HIGH},
+ climate::CLIMATE_FAN_HIGH, climate::CLIMATE_FAN_QUIET},
{climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL, climate::CLIMATE_SWING_HORIZONTAL,
climate::CLIMATE_SWING_BOTH}) {}
diff --git a/esphome/components/pca9685/pca9685_output.cpp b/esphome/components/pca9685/pca9685_output.cpp
index c61251b66f..d92312355a 100644
--- a/esphome/components/pca9685/pca9685_output.cpp
+++ b/esphome/components/pca9685/pca9685_output.cpp
@@ -29,13 +29,10 @@ void PCA9685Output::setup() {
ESP_LOGCONFIG(TAG, "Setting up PCA9685OutputComponent...");
ESP_LOGV(TAG, " Resetting devices...");
- uint8_t address_tmp = this->address_;
- this->set_i2c_address(0x00);
if (!this->write_bytes(PCA9685_REGISTER_SOFTWARE_RESET, nullptr, 0)) {
this->mark_failed();
return;
}
- this->set_i2c_address(address_tmp);
if (!this->write_byte(PCA9685_REGISTER_MODE1, PCA9685_MODE1_RESTART | PCA9685_MODE1_AUTOINC)) {
this->mark_failed();
diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py
index d8343c6c39..130c082277 100644
--- a/esphome/components/web_server/__init__.py
+++ b/esphome/components/web_server/__init__.py
@@ -81,6 +81,37 @@ CONFIG_SCHEMA = cv.All(
)
+def build_index_html(config) -> str:
+ html = "
"
+ css_include = config.get(CONF_CSS_INCLUDE)
+ js_include = config.get(CONF_JS_INCLUDE)
+ if css_include:
+ html += ""
+ if config[CONF_CSS_URL]:
+ html += f''
+ html += ""
+ if js_include:
+ html += ""
+ html += ""
+ if config[CONF_JS_URL]:
+ html += f''
+ html += ""
+ return html
+
+
+def add_resource_as_progmem(resource_name: str, content: str) -> None:
+ """Add a resource to progmem."""
+ content_encoded = content.encode("utf-8")
+ content_encoded_size = len(content_encoded)
+ bytes_as_int = ", ".join(str(x) for x in content_encoded)
+ uint8_t = f"const uint8_t ESPHOME_WEBSERVER_{resource_name}[{content_encoded_size}] PROGMEM = {{{bytes_as_int}}}"
+ size_t = (
+ f"const size_t ESPHOME_WEBSERVER_{resource_name}_SIZE = {content_encoded_size}"
+ )
+ cg.add_global(cg.RawExpression(uint8_t))
+ cg.add_global(cg.RawExpression(size_t))
+
+
@coroutine_with_priority(40.0)
async def to_code(config):
paren = await cg.get_variable(config[CONF_WEB_SERVER_BASE_ID])
@@ -89,13 +120,17 @@ async def to_code(config):
await cg.register_component(var, config)
cg.add_define("USE_WEBSERVER")
+ version = config[CONF_VERSION]
cg.add(paren.set_port(config[CONF_PORT]))
cg.add_define("USE_WEBSERVER")
cg.add_define("USE_WEBSERVER_PORT", config[CONF_PORT])
- cg.add_define("USE_WEBSERVER_VERSION", config[CONF_VERSION])
- cg.add(var.set_css_url(config[CONF_CSS_URL]))
- cg.add(var.set_js_url(config[CONF_JS_URL]))
+ cg.add_define("USE_WEBSERVER_VERSION", version)
+ if version == 2:
+ add_resource_as_progmem("INDEX_HTML", build_index_html(config))
+ else:
+ cg.add(var.set_css_url(config[CONF_CSS_URL]))
+ cg.add(var.set_js_url(config[CONF_JS_URL]))
cg.add(var.set_allow_ota(config[CONF_OTA]))
if CONF_AUTH in config:
cg.add(paren.set_auth_username(config[CONF_AUTH][CONF_USERNAME]))
@@ -103,13 +138,13 @@ async def to_code(config):
if CONF_CSS_INCLUDE in config:
cg.add_define("USE_WEBSERVER_CSS_INCLUDE")
path = CORE.relative_config_path(config[CONF_CSS_INCLUDE])
- with open(file=path, encoding="utf-8") as myfile:
- cg.add(var.set_css_include(myfile.read()))
+ with open(file=path, encoding="utf-8") as css_file:
+ add_resource_as_progmem("CSS_INCLUDE", css_file.read())
if CONF_JS_INCLUDE in config:
cg.add_define("USE_WEBSERVER_JS_INCLUDE")
path = CORE.relative_config_path(config[CONF_JS_INCLUDE])
- with open(file=path, encoding="utf-8") as myfile:
- cg.add(var.set_js_include(myfile.read()))
+ with open(file=path, encoding="utf-8") as js_file:
+ add_resource_as_progmem("JS_INCLUDE", js_file.read())
cg.add(var.set_include_internal(config[CONF_INCLUDE_INTERNAL]))
if CONF_LOCAL in config and config[CONF_LOCAL]:
cg.add_define("USE_WEBSERVER_LOCAL")
diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp
index 1ac94375c2..b3a2dfdb66 100644
--- a/esphome/components/web_server/web_server.cpp
+++ b/esphome/components/web_server/web_server.cpp
@@ -90,10 +90,17 @@ WebServer::WebServer(web_server_base::WebServerBase *base)
#endif
}
+#if USE_WEBSERVER_VERSION == 1
void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; }
-void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; }
void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; }
+#endif
+
+#ifdef USE_WEBSERVER_CSS_INCLUDE
+void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; }
+#endif
+#ifdef USE_WEBSERVER_JS_INCLUDE
void WebServer::set_js_include(const char *js_include) { this->js_include_ = js_include; }
+#endif
void WebServer::setup() {
ESP_LOGCONFIG(TAG, "Setting up web server...");
@@ -159,20 +166,14 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
-#else
+#elif USE_WEBSERVER_VERSION == 1
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
AsyncResponseStream *stream = request->beginResponseStream("text/html");
- // All content is controlled and created by user - so allowing all origins is fine here.
- stream->addHeader("Access-Control-Allow-Origin", "*");
-#if USE_WEBSERVER_VERSION == 1
const std::string &title = App.get_name();
stream->print(F(""));
stream->print(title.c_str());
stream->print(F(""));
-#else
- stream->print(F(""));
-#endif
#ifdef USE_WEBSERVER_CSS_INCLUDE
stream->print(F(""));
#endif
@@ -182,7 +183,6 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
stream->print(F("\">"));
}
stream->print(F(""));
-#if USE_WEBSERVER_VERSION == 1
stream->print(F(""));
stream->print(title.c_str());
stream->print(F("
"));
@@ -308,49 +308,40 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
"type=\"file\" name=\"update\">"));
}
stream->print(F("Debug Log
"));
-#endif
#ifdef USE_WEBSERVER_JS_INCLUDE
if (this->js_include_ != nullptr) {
stream->print(F(""));
}
-#endif
-#if USE_WEBSERVER_VERSION == 2
- stream->print(F(""));
#endif
if (strlen(this->js_url_) > 0) {
stream->print(F(""));
}
-#if USE_WEBSERVER_VERSION == 1
stream->print(F(""));
-#else
- stream->print(F(""));
-#endif
-
request->send(stream);
}
+#elif USE_WEBSERVER_VERSION == 2
+void WebServer::handle_index_request(AsyncWebServerRequest *request) {
+ AsyncWebServerResponse *response =
+ request->beginResponse_P(200, "text/html", ESPHOME_WEBSERVER_INDEX_HTML, ESPHOME_WEBSERVER_INDEX_HTML_SIZE);
+ request->send(response);
+}
#endif
+
#ifdef USE_WEBSERVER_CSS_INCLUDE
void WebServer::handle_css_request(AsyncWebServerRequest *request) {
- AsyncResponseStream *stream = request->beginResponseStream("text/css");
- if (this->css_include_ != nullptr) {
- stream->print(this->css_include_);
- }
-
- request->send(stream);
+ AsyncWebServerResponse *response =
+ request->beginResponse_P(200, "text/css", ESPHOME_WEBSERVER_CSS_INCLUDE, ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE);
+ request->send(response);
}
#endif
#ifdef USE_WEBSERVER_JS_INCLUDE
void WebServer::handle_js_request(AsyncWebServerRequest *request) {
- AsyncResponseStream *stream = request->beginResponseStream("text/javascript");
- if (this->js_include_ != nullptr) {
- stream->addHeader("Access-Control-Allow-Origin", "*");
- stream->print(this->js_include_);
- }
-
- request->send(stream);
+ AsyncWebServerResponse *response =
+ request->beginResponse_P(200, "text/javascript", ESPHOME_WEBSERVER_JS_INCLUDE, ESPHOME_WEBSERVER_JS_INCLUDE_SIZE);
+ request->send(response);
}
#endif
diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h
index 45d0bc03a4..a664bb5a12 100644
--- a/esphome/components/web_server/web_server.h
+++ b/esphome/components/web_server/web_server.h
@@ -14,6 +14,22 @@
#include
#include
#endif
+
+#if USE_WEBSERVER_VERSION == 2
+extern const uint8_t ESPHOME_WEBSERVER_INDEX_HTML[] PROGMEM;
+extern const size_t ESPHOME_WEBSERVER_INDEX_HTML_SIZE;
+#endif
+
+#ifdef USE_WEBSERVER_CSS_INCLUDE
+extern const uint8_t ESPHOME_WEBSERVER_CSS_INCLUDE[] PROGMEM;
+extern const size_t ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE;
+#endif
+
+#ifdef USE_WEBSERVER_JS_INCLUDE
+extern const uint8_t ESPHOME_WEBSERVER_JS_INCLUDE[] PROGMEM;
+extern const size_t ESPHOME_WEBSERVER_JS_INCLUDE_SIZE;
+#endif
+
namespace esphome {
namespace web_server {
@@ -40,6 +56,7 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
public:
WebServer(web_server_base::WebServerBase *base);
+#if USE_WEBSERVER_VERSION == 1
/** Set the URL to the CSS that's sent to each client. Defaults to
* https://esphome.io/_static/webserver-v1.min.css
*
@@ -47,24 +64,29 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
*/
void set_css_url(const char *css_url);
- /** Set local path to the script that's embedded in the index page. Defaults to
- *
- * @param css_include Local path to web server script.
- */
- void set_css_include(const char *css_include);
-
/** Set the URL to the script that's embedded in the index page. Defaults to
* https://esphome.io/_static/webserver-v1.min.js
*
* @param js_url The url to the web server script.
*/
void set_js_url(const char *js_url);
+#endif
+#ifdef USE_WEBSERVER_CSS_INCLUDE
+ /** Set local path to the script that's embedded in the index page. Defaults to
+ *
+ * @param css_include Local path to web server script.
+ */
+ void set_css_include(const char *css_include);
+#endif
+
+#ifdef USE_WEBSERVER_JS_INCLUDE
/** Set local path to the script that's embedded in the index page. Defaults to
*
* @param js_include Local path to web server script.
*/
void set_js_include(const char *js_include);
+#endif
/** Determine whether internal components should be displayed on the web server.
* Defaults to false.
@@ -240,10 +262,16 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
web_server_base::WebServerBase *base_;
AsyncEventSource events_{"/events"};
ListEntitiesIterator entities_iterator_;
+#if USE_WEBSERVER_VERSION == 1
const char *css_url_{nullptr};
- const char *css_include_{nullptr};
const char *js_url_{nullptr};
+#endif
+#ifdef USE_WEBSERVER_CSS_INCLUDE
+ const char *css_include_{nullptr};
+#endif
+#ifdef USE_WEBSERVER_JS_INCLUDE
const char *js_include_{nullptr};
+#endif
bool include_internal_{false};
bool allow_ota_{true};
#ifdef USE_ESP32
diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h
index f6d3a84f89..ae286b1e22 100644
--- a/esphome/components/web_server_base/web_server_base.h
+++ b/esphome/components/web_server_base/web_server_base.h
@@ -83,6 +83,7 @@ class WebServerBase : public Component {
return;
}
this->server_ = std::make_shared(this->port_);
+ // All content is controlled and created by user - so allowing all origins is fine here.
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
this->server_->begin();
diff --git a/esphome/const.py b/esphome/const.py
index d4cfd30c32..8d15ede755 100644
--- a/esphome/const.py
+++ b/esphome/const.py
@@ -1,6 +1,6 @@
"""Constants used by esphome."""
-__version__ = "2023.6.0b2"
+__version__ = "2023.6.0b3"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = (
diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp
index c012195f34..d82a7a5d37 100644
--- a/esphome/core/application.cpp
+++ b/esphome/core/application.cpp
@@ -99,7 +99,7 @@ void Application::loop() {
if (this->dump_config_at_ < this->components_.size()) {
if (this->dump_config_at_ == 0) {
- ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_.c_str());
+ ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_);
#ifdef ESPHOME_PROJECT_NAME
ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION);
#endif
diff --git a/esphome/core/application.h b/esphome/core/application.h
index 0501d1a56a..054f2ea648 100644
--- a/esphome/core/application.h
+++ b/esphome/core/application.h
@@ -56,7 +56,7 @@ namespace esphome {
class Application {
public:
- void pre_setup(const std::string &name, const std::string &friendly_name, const std::string &comment,
+ void pre_setup(const std::string &name, const std::string &friendly_name, const char *comment,
const char *compilation_time, bool name_add_mac_suffix) {
arch_init();
this->name_add_mac_suffix_ = name_add_mac_suffix;
@@ -154,11 +154,11 @@ class Application {
/// Get the friendly name of this Application set by pre_setup().
const std::string &get_friendly_name() const { return this->friendly_name_; }
/// Get the comment of this Application set by pre_setup().
- const std::string &get_comment() const { return this->comment_; }
+ std::string get_comment() const { return this->comment_; }
bool is_name_add_mac_suffix_enabled() const { return this->name_add_mac_suffix_; }
- const std::string &get_compilation_time() const { return this->compilation_time_; }
+ std::string get_compilation_time() const { return this->compilation_time_; }
/** Set the target interval with which to run the loop() calls.
* If the loop() method takes longer than the target interval, ESPHome won't
@@ -376,8 +376,8 @@ class Application {
std::string name_;
std::string friendly_name_;
- std::string comment_;
- std::string compilation_time_;
+ const char *comment_{nullptr};
+ const char *compilation_time_{nullptr};
bool name_add_mac_suffix_;
uint32_t last_loop_{0};
uint32_t loop_interval_{16};