mirror of
https://github.com/esphome/esphome.git
synced 2024-12-25 15:04:54 +01:00
Store preferences in disk file on host platform (#6428)
Co-authored-by: H. Árkosi Róbert <robreg@zsurob.hu> Co-authored-by: clydeps <U5yx99dok9>
This commit is contained in:
parent
e87727aed3
commit
121bd84854
2 changed files with 116 additions and 12 deletions
|
@ -1,36 +1,87 @@
|
|||
#ifdef USE_HOST
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include "preferences.h"
|
||||
#include <cstring>
|
||||
#include "esphome/core/preferences.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/application.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace host {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static const char *const TAG = "host.preferences";
|
||||
|
||||
class HostPreferences : public ESPPreferences {
|
||||
public:
|
||||
ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override { return {}; }
|
||||
void HostPreferences::setup_() {
|
||||
if (this->setup_complete_)
|
||||
return;
|
||||
this->filename_.append(getenv("HOME"));
|
||||
this->filename_.append("/.esphome");
|
||||
this->filename_.append("/prefs");
|
||||
fs::create_directories(this->filename_);
|
||||
this->filename_.append("/");
|
||||
this->filename_.append(App.get_name());
|
||||
this->filename_.append(".prefs");
|
||||
FILE *fp = fopen(this->filename_.c_str(), "rb");
|
||||
if (fp != nullptr) {
|
||||
while (!feof((fp))) {
|
||||
uint32_t key;
|
||||
uint8_t len;
|
||||
if (fread(&key, sizeof(key), 1, fp) != 1)
|
||||
break;
|
||||
if (fread(&len, sizeof(len), 1, fp) != 1)
|
||||
break;
|
||||
uint8_t data[len];
|
||||
if (fread(data, sizeof(uint8_t), len, fp) != len)
|
||||
break;
|
||||
std::vector vec(data, data + len);
|
||||
this->data[key] = vec;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
this->setup_complete_ = true;
|
||||
}
|
||||
|
||||
ESPPreferenceObject make_preference(size_t length, uint32_t type) override { return {}; }
|
||||
bool HostPreferences::sync() {
|
||||
this->setup_();
|
||||
FILE *fp = fopen(this->filename_.c_str(), "wb");
|
||||
std::map<uint32_t, std::vector<uint8_t>>::iterator it;
|
||||
|
||||
bool sync() override { return true; }
|
||||
bool reset() override { return true; }
|
||||
for (it = this->data.begin(); it != this->data.end(); ++it) {
|
||||
fwrite(&it->first, sizeof(uint32_t), 1, fp);
|
||||
uint8_t len = it->second.size();
|
||||
fwrite(&len, sizeof(len), 1, fp);
|
||||
fwrite(it->second.data(), sizeof(uint8_t), it->second.size(), fp);
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HostPreferences::reset() {
|
||||
host_preferences->data.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
ESPPreferenceObject HostPreferences::make_preference(size_t length, uint32_t type, bool in_flash) {
|
||||
auto backend = new HostPreferenceBackend(type);
|
||||
return ESPPreferenceObject(backend);
|
||||
};
|
||||
|
||||
void setup_preferences() {
|
||||
auto *pref = new HostPreferences(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
host_preferences = pref;
|
||||
global_preferences = pref;
|
||||
}
|
||||
|
||||
bool HostPreferenceBackend::save(const uint8_t *data, size_t len) {
|
||||
return host_preferences->save(this->key_, data, len);
|
||||
}
|
||||
|
||||
bool HostPreferenceBackend::load(uint8_t *data, size_t len) { return host_preferences->load(this->key_, data, len); }
|
||||
|
||||
HostPreferences *host_preferences;
|
||||
} // namespace host
|
||||
|
||||
ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_HOST
|
||||
|
|
|
@ -2,10 +2,63 @@
|
|||
|
||||
#ifdef USE_HOST
|
||||
|
||||
#include "esphome/core/preferences.h"
|
||||
#include <map>
|
||||
|
||||
namespace esphome {
|
||||
namespace host {
|
||||
|
||||
class HostPreferenceBackend : public ESPPreferenceBackend {
|
||||
public:
|
||||
explicit HostPreferenceBackend(uint32_t key) { this->key_ = key; }
|
||||
|
||||
bool save(const uint8_t *data, size_t len) override;
|
||||
bool load(uint8_t *data, size_t len) override;
|
||||
|
||||
protected:
|
||||
uint32_t key_{};
|
||||
};
|
||||
|
||||
class HostPreferences : public ESPPreferences {
|
||||
public:
|
||||
bool sync() override;
|
||||
bool reset() override;
|
||||
|
||||
ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override;
|
||||
ESPPreferenceObject make_preference(size_t length, uint32_t type) override {
|
||||
return make_preference(length, type, false);
|
||||
}
|
||||
|
||||
bool save(uint32_t key, const uint8_t *data, size_t len) {
|
||||
if (len > 255)
|
||||
return false;
|
||||
this->setup_();
|
||||
std::vector vec(data, data + len);
|
||||
this->data[key] = vec;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load(uint32_t key, uint8_t *data, size_t len) {
|
||||
if (len > 255)
|
||||
return false;
|
||||
this->setup_();
|
||||
if (this->data.count(key) == 0)
|
||||
return false;
|
||||
auto vec = this->data[key];
|
||||
if (vec.size() != len)
|
||||
return false;
|
||||
memcpy(data, vec.data(), len);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void setup_();
|
||||
bool setup_complete_{};
|
||||
std::string filename_{};
|
||||
std::map<uint32_t, std::vector<uint8_t>> data{};
|
||||
};
|
||||
void setup_preferences();
|
||||
extern HostPreferences *host_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace host
|
||||
} // namespace esphome
|
||||
|
|
Loading…
Reference in a new issue