mirror of
https://github.com/Threnklyn/esphome-dev.git
synced 2026-05-22 21:58:29 +02:00
Add Captive Portal (#624)
* WIP: Captive Portal * Updates * Updates * Lint * Fixes
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
extern "C" {
|
||||
#include "spi_flash.h"
|
||||
}
|
||||
@@ -12,9 +12,9 @@ namespace esphome {
|
||||
|
||||
static const char *TAG = "preferences";
|
||||
|
||||
ESPPreferenceObject::ESPPreferenceObject() : rtc_offset_(0), length_words_(0), type_(0), data_(nullptr) {}
|
||||
ESPPreferenceObject::ESPPreferenceObject(size_t rtc_offset, size_t length, uint32_t type)
|
||||
: rtc_offset_(rtc_offset), length_words_(length), type_(type) {
|
||||
ESPPreferenceObject::ESPPreferenceObject() : offset_(0), length_words_(0), type_(0), data_(nullptr) {}
|
||||
ESPPreferenceObject::ESPPreferenceObject(size_t offset, size_t length, uint32_t type)
|
||||
: offset_(offset), length_words_(length), type_(type) {
|
||||
this->data_ = new uint32_t[this->length_words_ + 1];
|
||||
for (uint32_t i = 0; i < this->length_words_ + 1; i++)
|
||||
this->data_[i] = 0;
|
||||
@@ -29,7 +29,7 @@ bool ESPPreferenceObject::load_() {
|
||||
|
||||
bool valid = this->data_[this->length_words_] == this->calculate_crc_();
|
||||
|
||||
ESP_LOGVV(TAG, "LOAD %u: valid=%s, 0=0x%08X 1=0x%08X (Type=%u, CRC=0x%08X)", this->rtc_offset_, // NOLINT
|
||||
ESP_LOGVV(TAG, "LOAD %u: valid=%s, 0=0x%08X 1=0x%08X (Type=%u, CRC=0x%08X)", this->offset_, // NOLINT
|
||||
YESNO(valid), this->data_[0], this->data_[1], this->type_, this->calculate_crc_());
|
||||
return valid;
|
||||
}
|
||||
@@ -42,7 +42,7 @@ bool ESPPreferenceObject::save_() {
|
||||
this->data_[this->length_words_] = this->calculate_crc_();
|
||||
if (!this->save_internal_())
|
||||
return false;
|
||||
ESP_LOGVV(TAG, "SAVE %u: 0=0x%08X 1=0x%08X (Type=%u, CRC=0x%08X)", this->rtc_offset_, // NOLINT
|
||||
ESP_LOGVV(TAG, "SAVE %u: 0=0x%08X 1=0x%08X (Type=%u, CRC=0x%08X)", this->offset_, // NOLINT
|
||||
this->data_[0], this->data_[1], this->type_, this->calculate_crc_());
|
||||
return true;
|
||||
}
|
||||
@@ -54,6 +54,12 @@ bool ESPPreferenceObject::save_() {
|
||||
#define ESP_RTC_USER_MEM_SIZE_WORDS 128
|
||||
#define ESP_RTC_USER_MEM_SIZE_BYTES ESP_RTC_USER_MEM_SIZE_WORDS * 4
|
||||
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
#define ESP8266_FLASH_STORAGE_SIZE 128
|
||||
#else
|
||||
#define ESP8266_FLASH_STORAGE_SIZE 64
|
||||
#endif
|
||||
|
||||
static inline bool esp_rtc_user_mem_read(uint32_t index, uint32_t *dest) {
|
||||
if (index >= ESP_RTC_USER_MEM_SIZE_WORDS) {
|
||||
return false;
|
||||
@@ -62,9 +68,7 @@ static inline bool esp_rtc_user_mem_read(uint32_t index, uint32_t *dest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
static bool esp8266_preferences_modified = false;
|
||||
#endif
|
||||
static bool esp8266_flash_dirty = false;
|
||||
|
||||
static inline bool esp_rtc_user_mem_write(uint32_t index, uint32_t value) {
|
||||
if (index >= ESP_RTC_USER_MEM_SIZE_WORDS) {
|
||||
@@ -75,29 +79,24 @@ static inline bool esp_rtc_user_mem_write(uint32_t index, uint32_t value) {
|
||||
}
|
||||
|
||||
auto *ptr = &ESP_RTC_USER_MEM[index];
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
if (*ptr != value) {
|
||||
esp8266_preferences_modified = true;
|
||||
}
|
||||
#endif
|
||||
*ptr = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
extern "C" uint32_t _SPIFFS_end;
|
||||
|
||||
static const uint32_t get_esp8266_flash_sector() { return (uint32_t(&_SPIFFS_end) - 0x40200000) / SPI_FLASH_SEC_SIZE; }
|
||||
static const uint32_t get_esp8266_flash_sector() {
|
||||
union {
|
||||
uint32_t *ptr;
|
||||
uint32_t uint;
|
||||
} data{};
|
||||
data.ptr = &_SPIFFS_end;
|
||||
return (data.uint - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
}
|
||||
static const uint32_t get_esp8266_flash_address() { return get_esp8266_flash_sector() * SPI_FLASH_SEC_SIZE; }
|
||||
|
||||
static void load_esp8266_flash() {
|
||||
ESP_LOGVV(TAG, "Loading preferences from flash...");
|
||||
disable_interrupts();
|
||||
spi_flash_read(get_esp8266_flash_address(), ESP_RTC_USER_MEM, ESP_RTC_USER_MEM_SIZE_BYTES);
|
||||
enable_interrupts();
|
||||
}
|
||||
static void save_esp8266_flash() {
|
||||
if (!esp8266_preferences_modified)
|
||||
void ESPPreferences::save_esp8266_flash_() {
|
||||
if (!esp8266_flash_dirty)
|
||||
return;
|
||||
|
||||
ESP_LOGVV(TAG, "Saving preferences to flash...");
|
||||
@@ -109,31 +108,53 @@ static void save_esp8266_flash() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto write_res = spi_flash_write(get_esp8266_flash_address(), ESP_RTC_USER_MEM, ESP_RTC_USER_MEM_SIZE_BYTES);
|
||||
auto write_res = spi_flash_write(get_esp8266_flash_address(), this->flash_storage_, ESP8266_FLASH_STORAGE_SIZE * 4);
|
||||
enable_interrupts();
|
||||
if (write_res != SPI_FLASH_RESULT_OK) {
|
||||
ESP_LOGV(TAG, "Write ESP8266 flash failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
esp8266_preferences_modified = false;
|
||||
esp8266_flash_dirty = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ESPPreferenceObject::save_internal_() {
|
||||
if (this->in_flash_) {
|
||||
for (uint32_t i = 0; i <= this->length_words_; i++) {
|
||||
uint32_t j = this->offset_ + i;
|
||||
if (j >= ESP8266_FLASH_STORAGE_SIZE)
|
||||
return false;
|
||||
uint32_t v = this->data_[i];
|
||||
uint32_t *ptr = &global_preferences.flash_storage_[j];
|
||||
if (*ptr != v)
|
||||
esp8266_flash_dirty = true;
|
||||
*ptr = v;
|
||||
}
|
||||
global_preferences.save_esp8266_flash_();
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i <= this->length_words_; i++) {
|
||||
if (!esp_rtc_user_mem_write(this->rtc_offset_ + i, this->data_[i]))
|
||||
if (!esp_rtc_user_mem_write(this->offset_ + i, this->data_[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
save_esp8266_flash();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
bool ESPPreferenceObject::load_internal_() {
|
||||
if (this->in_flash_) {
|
||||
for (uint32_t i = 0; i <= this->length_words_; i++) {
|
||||
uint32_t j = this->offset_ + i;
|
||||
if (j >= ESP8266_FLASH_STORAGE_SIZE)
|
||||
return false;
|
||||
this->data_[i] = global_preferences.flash_storage_[j];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i <= this->length_words_; i++) {
|
||||
if (!esp_rtc_user_mem_read(this->rtc_offset_ + i, &this->data_[i]))
|
||||
if (!esp_rtc_user_mem_read(this->offset_ + i, &this->data_[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -145,12 +166,25 @@ ESPPreferences::ESPPreferences()
|
||||
: current_offset_(0) {}
|
||||
|
||||
void ESPPreferences::begin(const std::string &name) {
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
load_esp8266_flash();
|
||||
#endif
|
||||
this->flash_storage_ = new uint32_t[ESP8266_FLASH_STORAGE_SIZE];
|
||||
ESP_LOGVV(TAG, "Loading preferences from flash...");
|
||||
disable_interrupts();
|
||||
spi_flash_read(get_esp8266_flash_address(), this->flash_storage_, ESP8266_FLASH_STORAGE_SIZE * 4);
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type) {
|
||||
ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type, bool in_flash) {
|
||||
if (in_flash) {
|
||||
uint32_t start = this->current_flash_offset_;
|
||||
uint32_t end = start + length + 1;
|
||||
if (end > ESP8266_FLASH_STORAGE_SIZE)
|
||||
return {};
|
||||
auto pref = ESPPreferenceObject(start, length, type);
|
||||
pref.in_flash_ = true;
|
||||
this->current_flash_offset_ = end;
|
||||
return pref;
|
||||
}
|
||||
|
||||
uint32_t start = this->current_offset_;
|
||||
uint32_t end = start + length + 1;
|
||||
bool in_normal = start < 96;
|
||||
@@ -165,7 +199,7 @@ ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type
|
||||
|
||||
if (end > 128) {
|
||||
// Doesn't fit in data, return uninitialized preference obj.
|
||||
return ESPPreferenceObject();
|
||||
return {};
|
||||
}
|
||||
|
||||
uint32_t rtc_offset;
|
||||
@@ -186,7 +220,7 @@ bool ESPPreferences::is_prevent_write() { return this->prevent_write_; }
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
bool ESPPreferenceObject::save_internal_() {
|
||||
char key[32];
|
||||
sprintf(key, "%u", this->rtc_offset_);
|
||||
sprintf(key, "%u", this->offset_);
|
||||
uint32_t len = (this->length_words_ + 1) * 4;
|
||||
size_t ret = global_preferences.preferences_.putBytes(key, this->data_, len);
|
||||
if (ret != len) {
|
||||
@@ -197,7 +231,7 @@ bool ESPPreferenceObject::save_internal_() {
|
||||
}
|
||||
bool ESPPreferenceObject::load_internal_() {
|
||||
char key[32];
|
||||
sprintf(key, "%u", this->rtc_offset_);
|
||||
sprintf(key, "%u", this->offset_);
|
||||
uint32_t len = (this->length_words_ + 1) * 4;
|
||||
size_t ret = global_preferences.preferences_.getBytes(key, this->data_, len);
|
||||
if (ret != len) {
|
||||
@@ -213,7 +247,7 @@ void ESPPreferences::begin(const std::string &name) {
|
||||
this->preferences_.begin(key.c_str());
|
||||
}
|
||||
|
||||
ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type) {
|
||||
ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type, bool in_flash) {
|
||||
auto pref = ESPPreferenceObject(this->current_offset_, length, type);
|
||||
this->current_offset_++;
|
||||
return pref;
|
||||
|
||||
Reference in New Issue
Block a user