// // FILE: Config.h // VERSION: 0.1 // PURPOSE: Configuration of controller, wifi and application basics // // #include "DjConfig.h" #include #include #ifdef ESP8266 extern "C" { #include "user_interface.h" } #endif #define DEFAULT_CONFIG_JSON "{default:true}" struct ConfigItem { String section; String name; String type; String value; boolean changed; }; static struct ConfigItem configItems[MAX_NUMBER_OF_CONFIG_ITEMS]; static int numberOfConfigItems = 0; static StaticJsonDocument<2000> jsonDoc; void Config::loadFile(const char *filename, const char * const sectionConfigItemDescriptions[], int numberOfSectionConfigs) { boolean fileExists = false; boolean fileConfigIsComplete = true; static const char *defaultJsonString = "{\"empty\"=\"empty\"}"; logHeap(); debug.out(F(">>> loadFile ")); debug.outln(filename); _filename = String(filename); if (!_filename.startsWith("/")) _filename = "/" + _filename; boolean jsonLoaded = false; if (SPIFFS.exists(_filename)) { //file exists, reading and loading fileExists = true; debug.out(F("reading config file "),DEBUG_MIN_INFO); debug.outln(_filename); File configFile = SPIFFS.open(_filename, "r"); if (configFile) { size_t size = configFile.size(); configFile.seek(0, SeekSet); debug.out(F("opened config file "),DEBUG_MIN_INFO); debug.out(_filename,DEBUG_MIN_INFO); debug.out(F(" size=")); debug.outln(size); DeserializationError error = deserializeJson(jsonDoc, configFile); configFile.close(); if (error) { debug.out(F("Failed to read file, using default configuration"), DEBUG_ERROR); deserializeJson(jsonDoc, defaultJsonString); } else { debug.out(F("readBytes result=")); debug.outln(size); jsonLoaded = true; } } else { debug.outln(F("ERROR: config file exists but cannot be opened."),DEBUG_ERROR); deserializeJson(jsonDoc, defaultJsonString); } } else { debug.outln(F("config file not found ..."),DEBUG_MED_INFO); deserializeJson(jsonDoc, defaultJsonString); } // end of if file exists // end of mounted file system (we want to have default config, if no FS available) // start setting the config variables for (int i=0; i 0) { configItems[numberOfConfigItems].section = filename; int firstColon = configItemDescription.indexOf(":"); int secondColon = configItemDescription.indexOf(":", firstColon+1); configItems[numberOfConfigItems].name = configItemDescription.substring(0, firstColon); configItems[numberOfConfigItems].type = configItemDescription.substring(firstColon+1, secondColon); debug.out(F("Adding config item: [")); debug.out(configItems[numberOfConfigItems].section); debug.out(F("] ")); debug.out(configItems[numberOfConfigItems].name); if (jsonLoaded && jsonDoc[configItems[numberOfConfigItems].name] != NULL) { if (configItems[numberOfConfigItems].type.equals("int")) { configItems[numberOfConfigItems].value = String((int) jsonDoc[configItems[numberOfConfigItems].name]); } else if (configItems[numberOfConfigItems].type.equals("boolean")) { configItems[numberOfConfigItems].value = String(jsonDoc[configItems[numberOfConfigItems].name] ? "true" : "false"); } else if (configItems[numberOfConfigItems].type.equals("string")) { configItems[numberOfConfigItems].value = String((const char *) jsonDoc[configItems[numberOfConfigItems].name]); } else { debug.out(F("ERROR: Unknown type in config definition - "), DEBUG_ERROR); debug.outln(configItems[numberOfConfigItems].type, DEBUG_ERROR); } debug.out(F(" (from file): ")); } else { // parameter does not exist in json config file, thus we add the default value fileConfigIsComplete = false; configItems[numberOfConfigItems].value = configItemDescription.substring(secondColon+1); debug.out(F(" (from default): ")); } debug.out(configItems[numberOfConfigItems].value); debug.out(F(" (")); debug.out(configItems[numberOfConfigItems].type); debug.out(F(")")); configItems[numberOfConfigItems].changed = false; numberOfConfigItems++; if (numberOfConfigItems >= MAX_NUMBER_OF_CONFIG_ITEMS) { debug.outln(F("ERROR: Too many configuration items!"),DEBUG_ERROR); break; } else { debug.out(F(" [")); debug.out(numberOfConfigItems); debug.out(F("] ")); } logHeap(); } } // end for ... numberOfSectionConfigs ... logHeap(); // Finally, if the configuration file does not exist so far or new entries have been added, then create/update it: if (!fileExists || !fileConfigIsComplete) { debug.outln(F("Writing config file due to ")); if (!fileExists) debug.outln(F(" - file does not exist ")); if (!fileConfigIsComplete) debug.outln(F(" - file config is not complete")); debug.outln(_filename); writeConfigFile(_filename); } } void Config::writeAllConfigs(void) { boolean allChangesWritten = false; logHeap(); while (!allChangesWritten) { for (int i=0; i json; for (int i=0; igetString(key).toInt(); } void Config::setInt(String parameter, int value) { this->setString(parameter, String(value)); } boolean Config::getBoolean(String key) { String sval = getString(key); boolean bval = false; if (sval.length() > 0) { if (sval.equals("true") || sval.equals("TRUE")) { bval = true; } else if (sval.equals("false") || sval.equals("FALSE")) { bval = false; } else { int ival = sval.toInt(); if (ival) { bval = true; } } return bval; } else { return false; } } void Config::setBoolean(String parameter, boolean value) { this->setString(parameter, value ? "true" : "false"); }