diff --git a/.travis.yml b/.travis.yml index 1a547a1..65799b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,6 +55,23 @@ jobs: script: - platformio ci --lib="." --board=nodemcuv2 --project-option="lib_deps=ESP Async WebServer, ArduinoJSON" + - stage: Framework + name: "configManager Example" + language: python + python: + - "2.7" + sudo: false + cache: + directories: + - "~/.platformio" + env: + - PLATFORMIO_CI_SRC=examples/configManager/configManagerExample.cpp + install: + - pip install -U platformio + - platformio update + script: + - platformio ci --lib="." --board=nodemcuv2 --project-option="lib_deps=ESP Async WebServer, ArduinoJSON" + - stage: Framework name: "Time Sync Example" language: python diff --git a/docs/config-manager.md b/docs/config-manager.md index 5bc2310..037d24a 100644 --- a/docs/config-manager.md +++ b/docs/config-manager.md @@ -4,6 +4,8 @@ For whatever function a device with an ESP8266 might have, it could be that you Usage of this class is easy. See below how to define your configuration parameters. Once you have done this, these can be changed from the browser, and simply be called in the rest of your application as `configManager.data.parameterName`. +A more detailed example of how to use this in your code is in the examples folder. + ## Class Methods #### begin @@ -13,10 +15,24 @@ bool begin(int numBytes = 512); ``` This method must be called from the setup of the application. The optional argument will determine the flash size used for EEPROM. The method will attempt to restore the saved data from EEPROM. If no data is available, or if the fingerprint of the data structure has changed, the default values will be used. +#### save + +```c++ +void saveRaw(); +``` +This method saves the configManager.data object to EEPROM. Use this if you write changes or updates directly to the RAM mirror + +#### saveRaw + +```c++ +void saveExternal(configData *extData); +``` +This method copies an external configData object into the configManager.data RAM mirror, and uploads it to EEPROM. + #### saveRaw ```c++ -void saveRaw(uint8_t test[]); +void saveRaw(uint8_t bytes[]); ``` This method stores the input byte array into the EEPROM. This is an unsafe method, you must ensure externally that the input byte array is the correct length and structure. @@ -46,10 +62,6 @@ You might have noticed that the API only gives a function to update the full con On the low level then the full block will be rewritten. The reason for this implementation is that typically nothing is gained by writing individual members. The ESP8266 has no real EEPROM. The EEPROM class will rather write the content to a flash block. Since Flash memory can only be erased in blocks you have to wipe the whole lot and rewrite it. To prevent abusing the flash by potentially looping over a save function for individual members, this function is simply not available, enforcing you to only write the entire block at once. -## Updating from the C++ code - -Of course you can also update configuration information from your code rather than through the web interface. To do this you need to make a RAM mirror of the `configManager.data` object. After you have modified the content of this object, you can simply give a pointer to its contents as an argument to the `configManager.saveRaw` function to store the result in EEPROM. - ## Code Generation The configuration data is defined in the JSON file `html/js/configuration.json`. @@ -60,7 +72,11 @@ However, if you use the framework as a PlatformIO library, you need to define th build_flags = -DCONFIG_PATH=configuration_filename.json ``` -This configuration file will be automatically copied into the library folder before each build. An example of how this file could look is shown below. +This configuration file will be automatically copied into the library folder before each build. + +**Important:** After you have changed the JSON file, you also need to regenerate the web interface to reflect the latest changes by enabling the REBUILD_HTML build flag, otherwise the web interface will show the old configData. Refer to [this section](https://github.com/maakbaas/esp8266-iot-framework/blob/master/docs/getting-started.md#editing-the-web-interface) for more details. + +An example of how this file could look is shown below: ```json [ diff --git a/examples/configManager/configManagerExample.cpp b/examples/configManager/configManagerExample.cpp new file mode 100644 index 0000000..8b7b09d --- /dev/null +++ b/examples/configManager/configManagerExample.cpp @@ -0,0 +1,65 @@ +#include +#include "LittleFS.h" + +#include "WiFiManager.h" +#include "webServer.h" +#include "updater.h" +#include "fetch.h" +#include "configManager.h" +#include "timeSync.h" + +struct task +{ + unsigned long rate; + unsigned long previous; +}; + +task taskA = {.rate = 60000, .previous = 0}; + +void setup() +{ + Serial.begin(115200); + + LittleFS.begin(); + GUI.begin(); + configManager.begin(); + WiFiManager.begin(configManager.data.projectName); + timeSync.begin(); +} + +void loop() +{ + //software interrupts + WiFiManager.loop(); + updater.loop(); + + //task A + if (taskA.previous == 0 || (millis() - taskA.previous > taskA.rate)) + { + taskA.previous = millis(); + + //option 1: + //write directly to the configData ram mirror + configManager.data.dummyInt++; + + //save the newest values in the EEPROM + configManager.save(); + + + //option 2: + //create a new config data object + //in this case make sure you set all values + configData newData = + { + "Generic ESP8266 Firmware", + configManager.data.dummyInt + 1, + true, + 1.2345, + "invisible!" + }; + + ///The saveExternal function copies the object to EEPROM + configManager.saveExternal(&newData); + + } +} diff --git a/library.json b/library.json index def908a..7309201 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ESP8266 IoT Framework", - "version": "1.2.0", + "version": "1.3.0", "description": "Framework for IoT projects implementing HTTPS requests, a React web interface, WiFi manager, configuration manager, file manager and OTA updates.", "keywords": "esp8266,react,ota-updates,wifi-manager,https,file-manager", "frameworks": "arduino", @@ -37,6 +37,13 @@ "fetchExample.cpp" ] }, + { + "name": "configManager", + "base": "examples/configManager", + "files": [ + "configManagerExample.cpp" + ] + }, { "name": "timeSync", "base": "examples/timeSync", diff --git a/src/configManager.cpp b/src/configManager.cpp index 39d5c11..7f0228d 100644 --- a/src/configManager.cpp +++ b/src/configManager.cpp @@ -1,45 +1,51 @@ -#include - -#include "configManager.h" - -//class functions -bool config::begin(int numBytes) -{ - EEPROM.begin(numBytes); - - uint32_t storedVersion; - EEPROM.get(0, storedVersion); - if (storedVersion != configVersion) - { - reset(); - return false; - } - else - { - EEPROM.get(4, data); - - return true; - } - -} - -void config::reset() -{ - memcpy_P(&data, &defaults, sizeof(data)); - save(); -} - -void config::saveRaw(uint8_t test[]) -{ - memcpy(&data,test,sizeof(data)); - save(); -} - -void config::save() -{ - EEPROM.put(0, configVersion); - EEPROM.put(4, data); - EEPROM.commit(); -} - +#include + +#include "configManager.h" + +//class functions +bool config::begin(int numBytes) +{ + EEPROM.begin(numBytes); + + uint32_t storedVersion; + EEPROM.get(0, storedVersion); + if (storedVersion != configVersion) + { + reset(); + return false; + } + else + { + EEPROM.get(4, data); + + return true; + } + +} + +void config::reset() +{ + memcpy_P(&data, &defaults, sizeof(data)); + save(); +} + +void config::saveRaw(uint8_t bytes[]) +{ + memcpy(&data,bytes,sizeof(data)); + save(); +} + +void config::saveExternal(configData *extData) +{ + memcpy(&data, extData, sizeof(data)); + save(); +} + +void config::save() +{ + EEPROM.put(0, configVersion); + EEPROM.put(4, data); + EEPROM.commit(); +} + config configManager; \ No newline at end of file diff --git a/src/configManager.h b/src/configManager.h index 6706827..ddacf27 100644 --- a/src/configManager.h +++ b/src/configManager.h @@ -1,21 +1,21 @@ -#ifndef CONFIGMGR_H -#define CONFIGMGR_H - -#include "generated/config.h" - -class config -{ - -public: - configData data; - bool begin(int numBytes = 512); - void saveRaw(uint8_t test[]); - void reset(); - -private: - void save(); -}; - -extern config configManager; - +#ifndef CONFIGMGR_H +#define CONFIGMGR_H + +#include "generated/config.h" + +class config +{ + +public: + configData data; + bool begin(int numBytes = 512); + void saveRaw(uint8_t bytes[]); + void saveExternal(configData *extData); + void save(); + void reset(); + +}; + +extern config configManager; + #endif \ No newline at end of file