/* SETTINGS MODULE Copyright (C) 2016-2019 by Xose PĂ©rez */ #pragma once #include #include #include #include #include #include #include "broker.h" #include "storage_eeprom.h" #include "settings_embedis.h" BrokerDeclare(ConfigBroker, void(const String& key, const String& value)); // -------------------------------------------------------------------------- void resetSettings(); void saveSettings(); void autosaveSettings(); namespace settings { class EepromStorage { public: uint8_t read(size_t pos) { return eepromRead(pos); } void write(size_t pos, uint8_t value) { eepromWrite(pos, value); } void commit() { autosaveSettings(); } }; using kvs_type = embedis::KeyValueStore; extern kvs_type kv_store; } // namespace settings // -------------------------------------------------------------------------- class SettingsKey { public: SettingsKey(const char* key) : _key(key) {} SettingsKey(const String& key) : _key(key) {} SettingsKey(String&& key) : _key(std::move(key)) {} SettingsKey(const String& prefix, unsigned char index) { _key.reserve(prefix.length()); _key += prefix; _key += index; } SettingsKey(String&& prefix, unsigned char index) : _key(std::move(prefix)) { _key += index; } SettingsKey(const char* prefix, unsigned char index) : _key(prefix) { _key += index; } bool operator==(const char* other) const { return _key == other; } bool operator==(const String& other) const { return _key == other; } const String& toString() const { return _key; } explicit operator String() const & { return _key; } explicit operator String() && { return std::move(_key); } private: String _key; }; using settings_move_key_t = std::pair; using settings_filter_t = std::function; // -------------------------------------------------------------------------- struct settings_cfg_t { String& setting; const char* key; const char* default_value; }; using settings_cfg_list_t = std::initializer_list; // -------------------------------------------------------------------------- namespace settings { namespace internal { template using is_arduino_string = std::is_same::type>; template using enable_if_arduino_string = std::enable_if::value>; template using enable_if_not_arduino_string = std::enable_if::value>; // -------------------------------------------------------------------------- uint32_t u32fromString(const String& string, int base); template T convert(const String& value); // -------------------------------------------------------------------------- template <> float convert(const String& value); template <> double convert(const String& value); template <> int convert(const String& value); template <> long convert(const String& value); template <> bool convert(const String& value); template <> unsigned long convert(const String& value); template <> unsigned int convert(const String& value); template <> unsigned short convert(const String& value); template <> unsigned char convert(const String& value); template String serialize(const T& value); } // namespace internal } // namespace settings // -------------------------------------------------------------------------- struct settings_key_match_t { using match_f = bool(*)(const char* key); using key_f = const String(*)(const String& key); match_f match; key_f key; }; void settingsRegisterDefaults(const settings_key_match_t& matcher); String settingsQueryDefaults(const String& key); // -------------------------------------------------------------------------- void moveSetting(const String& from, const String& to); void moveSetting(const String& from, const String& to, unsigned int index); void moveSettings(const String& from, const String& to); template ::type> T getSetting(const SettingsKey& key, T defaultValue) __attribute__((noinline)); template ::type> T getSetting(const SettingsKey& key, T defaultValue) { auto result = settings::kv_store.get(key.toString()); if (!result) { return defaultValue; } return settings::internal::convert(result.value); } String getSetting(const char* key); String getSetting(const String& key); String getSetting(const __FlashStringHelper* key); String getSetting(const SettingsKey& key); String getSetting(const SettingsKey& key, const char* defaultValue); String getSetting(const SettingsKey& key, const __FlashStringHelper* defaultValue); String getSetting(const SettingsKey& key, const String& defaultValue); String getSetting(const SettingsKey& key, const String& defaultValue); String getSetting(const SettingsKey& key, String&& defaultValue); template::type> bool setSetting(const SettingsKey& key, T&& value) { return settings::kv_store.set(key.toString(), value); } template::type> bool setSetting(const SettingsKey& key, T value) { return setSetting(key, std::move(String(value))); } bool delSetting(const char* key); bool delSetting(const String& key); bool delSetting(const __FlashStringHelper* key); bool delSetting(const SettingsKey& key); void delSettingPrefix(const std::initializer_list&); void delSettingPrefix(const char* prefix); void delSettingPrefix(const String& prefix); bool hasSetting(const char* key); bool hasSetting(const String& key); bool hasSetting(const __FlashStringHelper* key); bool hasSetting(const SettingsKey& key); void settingsGetJson(JsonObject& data); bool settingsRestoreJson(char* json_string, size_t json_buffer_size = 1024); bool settingsRestoreJson(JsonObject& data); size_t settingsKeyCount(); std::vector settingsKeys(); void settingsProcessConfig(const settings_cfg_list_t& config, settings_filter_t filter = nullptr); size_t settingsSize(); void settingsSetup(); // ----------------------------------------------------------------------------- // Configuration updates // ----------------------------------------------------------------------------- int migrateVersion(); void migrate(); // ----------------------------------------------------------------------------- // Deprecated implementation // ----------------------------------------------------------------------------- template String getSetting(const String& key, unsigned char index, T defaultValue) __attribute__((deprecated("getSetting({key, index}, default) should be used instead"))); template bool setSetting(const String& key, unsigned char index, T value) __attribute__((deprecated("setSetting({key, index}, value) should be used instead"))); template bool hasSetting(const String& key, unsigned char index) __attribute__((deprecated("hasSetting({key, index}) should be used instead"))); template bool delSetting(const String& key, unsigned char index) __attribute__((deprecated("delSetting({key, index}) should be used instead"))); // -------------------------------------------------------------------------- template String getSetting(const String& key, unsigned char index, T defaultValue) { return getSetting({key, index}, defaultValue); } template bool setSetting(const String& key, unsigned char index, T value) { return setSetting({key, index}, value); } template bool hasSetting(const String& key, unsigned char index) { return hasSetting({key, index}); } template bool delSetting(const String& key, unsigned char index) { return delSetting({key, index}); }