mirror of
https://github.com/esphome/esphome.git
synced 2025-10-31 23:21:54 +00:00
[wifi] Store credentials in PROGMEM on ESP8266 to reduce RAM usage
This commit is contained in:
@@ -140,17 +140,21 @@ EAP_AUTH_SCHEMA = cv.All(
|
||||
cv.has_at_least_one_key(CONF_IDENTITY, CONF_CERTIFICATE),
|
||||
)
|
||||
|
||||
CONF_AP_TIMEOUT = "ap_timeout"
|
||||
CONF_SSID_DATA_ID = "ssid_data_id"
|
||||
CONF_PASSWORD_DATA_ID = "password_data_id"
|
||||
|
||||
WIFI_NETWORK_BASE = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(WiFiAP),
|
||||
cv.GenerateID(CONF_SSID_DATA_ID): cv.declare_id(cg.uint8),
|
||||
cv.GenerateID(CONF_PASSWORD_DATA_ID): cv.declare_id(cg.uint8),
|
||||
cv.Optional(CONF_SSID): cv.ssid,
|
||||
cv.Optional(CONF_PASSWORD): validate_password,
|
||||
cv.Optional(CONF_CHANNEL): validate_channel,
|
||||
cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA,
|
||||
}
|
||||
)
|
||||
|
||||
CONF_AP_TIMEOUT = "ap_timeout"
|
||||
WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend(
|
||||
{
|
||||
cv.Optional(
|
||||
@@ -352,9 +356,23 @@ def manual_ip(config):
|
||||
|
||||
def wifi_network(config, ap, static_ip):
|
||||
if CONF_SSID in config:
|
||||
cg.add(ap.set_ssid(config[CONF_SSID]))
|
||||
ssid = config[CONF_SSID]
|
||||
if CORE.is_esp8266:
|
||||
# On ESP8266, store SSID in PROGMEM to save RAM
|
||||
prog_arr = cg.progmem_array(config[CONF_SSID_DATA_ID], ssid)
|
||||
cg.add(ap.set_ssid_flash(prog_arr))
|
||||
else:
|
||||
# On ESP32/RP2040, string literals are already in rodata (flash)
|
||||
cg.add(ap.set_ssid_flash(ssid))
|
||||
if CONF_PASSWORD in config:
|
||||
cg.add(ap.set_password(config[CONF_PASSWORD]))
|
||||
password = config[CONF_PASSWORD]
|
||||
if CORE.is_esp8266:
|
||||
# On ESP8266, store password in PROGMEM to save RAM
|
||||
prog_arr = cg.progmem_array(config[CONF_PASSWORD_DATA_ID], password)
|
||||
cg.add(ap.set_password_flash(prog_arr))
|
||||
else:
|
||||
# On ESP32/RP2040, string literals are already in rodata (flash)
|
||||
cg.add(ap.set_password_flash(password))
|
||||
if CONF_EAP in config:
|
||||
cg.add(ap.set_eap(eap_auth(config[CONF_EAP])))
|
||||
cg.add_define("USE_WIFI_WPA2_EAP")
|
||||
|
||||
@@ -888,19 +888,68 @@ void WiFiComponent::save_fast_connect_settings_() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void WiFiAP::set_ssid(const std::string &ssid) { this->ssid_ = ssid; }
|
||||
void WiFiAP::set_ssid(const std::string &ssid) {
|
||||
this->ssid_storage_ = ssid;
|
||||
this->ssid_ = this->ssid_storage_->c_str();
|
||||
}
|
||||
void WiFiAP::set_bssid(bssid_t bssid) { this->bssid_ = bssid; }
|
||||
void WiFiAP::set_bssid(optional<bssid_t> bssid) { this->bssid_ = bssid; }
|
||||
void WiFiAP::set_password(const std::string &password) { this->password_ = password; }
|
||||
void WiFiAP::set_password(const std::string &password) {
|
||||
this->password_storage_ = password;
|
||||
this->password_ = this->password_storage_->c_str();
|
||||
}
|
||||
#ifdef USE_ESP8266
|
||||
void WiFiAP::set_ssid_flash(const uint8_t *ssid) {
|
||||
this->ssid_storage_.reset();
|
||||
this->ssid_ = reinterpret_cast<const char *>(ssid);
|
||||
}
|
||||
void WiFiAP::set_password_flash(const uint8_t *password) {
|
||||
this->password_storage_.reset();
|
||||
this->password_ = reinterpret_cast<const char *>(password);
|
||||
}
|
||||
#else
|
||||
void WiFiAP::set_ssid_flash(const char *ssid) {
|
||||
this->ssid_storage_.reset();
|
||||
this->ssid_ = ssid;
|
||||
}
|
||||
void WiFiAP::set_password_flash(const char *password) {
|
||||
this->password_storage_.reset();
|
||||
this->password_ = password;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
void WiFiAP::set_eap(optional<EAPAuth> eap_auth) { this->eap_ = std::move(eap_auth); }
|
||||
#endif
|
||||
void WiFiAP::set_channel(optional<uint8_t> channel) { this->channel_ = channel; }
|
||||
void WiFiAP::set_manual_ip(optional<ManualIP> manual_ip) { this->manual_ip_ = manual_ip; }
|
||||
void WiFiAP::set_hidden(bool hidden) { this->hidden_ = hidden; }
|
||||
const std::string &WiFiAP::get_ssid() const { return this->ssid_; }
|
||||
std::string WiFiAP::get_ssid() const {
|
||||
#ifdef USE_ESP8266
|
||||
if (!this->ssid_storage_.has_value()) {
|
||||
// Flash storage - read from PROGMEM
|
||||
size_t len = strlen_P(this->ssid_);
|
||||
std::string result;
|
||||
result.resize(len);
|
||||
memcpy_P(&result[0], this->ssid_, len);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
return std::string(this->ssid_);
|
||||
}
|
||||
const optional<bssid_t> &WiFiAP::get_bssid() const { return this->bssid_; }
|
||||
const std::string &WiFiAP::get_password() const { return this->password_; }
|
||||
std::string WiFiAP::get_password() const {
|
||||
#ifdef USE_ESP8266
|
||||
if (!this->password_storage_.has_value()) {
|
||||
// Flash storage - read from PROGMEM
|
||||
size_t len = strlen_P(this->password_);
|
||||
std::string result;
|
||||
result.resize(len);
|
||||
memcpy_P(&result[0], this->password_, len);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
return std::string(this->password_);
|
||||
}
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
const optional<EAPAuth> &WiFiAP::get_eap() const { return this->eap_; }
|
||||
#endif
|
||||
|
||||
@@ -135,6 +135,18 @@ class WiFiAP {
|
||||
void set_bssid(bssid_t bssid);
|
||||
void set_bssid(optional<bssid_t> bssid);
|
||||
void set_password(const std::string &password);
|
||||
/// Set SSID from flash string (PROGMEM on ESP8266, rodata on ESP32)
|
||||
#ifdef USE_ESP8266
|
||||
void set_ssid_flash(const uint8_t *ssid);
|
||||
#else
|
||||
void set_ssid_flash(const char *ssid);
|
||||
#endif
|
||||
/// Set password from flash string (PROGMEM on ESP8266, rodata on ESP32)
|
||||
#ifdef USE_ESP8266
|
||||
void set_password_flash(const uint8_t *password);
|
||||
#else
|
||||
void set_password_flash(const char *password);
|
||||
#endif
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
void set_eap(optional<EAPAuth> eap_auth);
|
||||
#endif // USE_WIFI_WPA2_EAP
|
||||
@@ -142,9 +154,9 @@ class WiFiAP {
|
||||
void set_priority(float priority) { priority_ = priority; }
|
||||
void set_manual_ip(optional<ManualIP> manual_ip);
|
||||
void set_hidden(bool hidden);
|
||||
const std::string &get_ssid() const;
|
||||
std::string get_ssid() const;
|
||||
const optional<bssid_t> &get_bssid() const;
|
||||
const std::string &get_password() const;
|
||||
std::string get_password() const;
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
const optional<EAPAuth> &get_eap() const;
|
||||
#endif // USE_WIFI_WPA2_EAP
|
||||
@@ -154,8 +166,10 @@ class WiFiAP {
|
||||
bool get_hidden() const;
|
||||
|
||||
protected:
|
||||
std::string ssid_;
|
||||
std::string password_;
|
||||
const char *ssid_{nullptr};
|
||||
const char *password_{nullptr};
|
||||
optional<std::string> ssid_storage_;
|
||||
optional<std::string> password_storage_;
|
||||
optional<bssid_t> bssid_;
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
optional<EAPAuth> eap_;
|
||||
|
||||
@@ -236,16 +236,25 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
||||
|
||||
struct station_config conf {};
|
||||
memset(&conf, 0, sizeof(conf));
|
||||
if (ap.get_ssid().size() > sizeof(conf.ssid)) {
|
||||
|
||||
std::string ssid = ap.get_ssid();
|
||||
std::string password = ap.get_password();
|
||||
|
||||
size_t ssid_len = ssid.length();
|
||||
size_t password_len = password.length();
|
||||
|
||||
if (ssid_len > sizeof(conf.ssid)) {
|
||||
ESP_LOGE(TAG, "SSID too long");
|
||||
return false;
|
||||
}
|
||||
if (ap.get_password().size() > sizeof(conf.password)) {
|
||||
|
||||
if (password_len > sizeof(conf.password)) {
|
||||
ESP_LOGE(TAG, "Password too long");
|
||||
return false;
|
||||
}
|
||||
memcpy(reinterpret_cast<char *>(conf.ssid), ap.get_ssid().c_str(), ap.get_ssid().size());
|
||||
memcpy(reinterpret_cast<char *>(conf.password), ap.get_password().c_str(), ap.get_password().size());
|
||||
|
||||
memcpy(conf.ssid, ssid.c_str(), ssid_len);
|
||||
memcpy(conf.password, password.c_str(), password_len);
|
||||
|
||||
if (ap.get_bssid().has_value()) {
|
||||
conf.bssid_set = 1;
|
||||
@@ -791,27 +800,35 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
|
||||
return false;
|
||||
|
||||
struct softap_config conf {};
|
||||
if (ap.get_ssid().size() > sizeof(conf.ssid)) {
|
||||
|
||||
std::string ssid = ap.get_ssid();
|
||||
std::string password = ap.get_password();
|
||||
|
||||
size_t ssid_len = ssid.length();
|
||||
size_t password_len = password.length();
|
||||
|
||||
if (ssid_len > sizeof(conf.ssid)) {
|
||||
ESP_LOGE(TAG, "AP SSID too long");
|
||||
return false;
|
||||
}
|
||||
memcpy(reinterpret_cast<char *>(conf.ssid), ap.get_ssid().c_str(), ap.get_ssid().size());
|
||||
conf.ssid_len = static_cast<uint8>(ap.get_ssid().size());
|
||||
|
||||
memcpy(conf.ssid, ssid.c_str(), ssid_len);
|
||||
conf.ssid_len = static_cast<uint8>(ssid_len);
|
||||
conf.channel = ap.get_channel().value_or(1);
|
||||
conf.ssid_hidden = ap.get_hidden();
|
||||
conf.max_connection = 5;
|
||||
conf.beacon_interval = 100;
|
||||
|
||||
if (ap.get_password().empty()) {
|
||||
if (password_len == 0) {
|
||||
conf.authmode = AUTH_OPEN;
|
||||
*conf.password = 0;
|
||||
} else {
|
||||
conf.authmode = AUTH_WPA2_PSK;
|
||||
if (ap.get_password().size() > sizeof(conf.password)) {
|
||||
if (password_len > sizeof(conf.password)) {
|
||||
ESP_LOGE(TAG, "AP password too long");
|
||||
return false;
|
||||
}
|
||||
memcpy(reinterpret_cast<char *>(conf.password), ap.get_password().c_str(), ap.get_password().size());
|
||||
memcpy(conf.password, password.c_str(), password_len);
|
||||
}
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
|
||||
Reference in New Issue
Block a user