├── .gitignore
├── CHANGES.txt
├── LICENSE
├── README.md
├── docs
├── config.png
└── config_colapsed.png
├── examples
├── ConfigAssist-Dynamic
│ └── ConfigAssist-Dynamic.ino
├── ConfigAssist-ESP32-ESP8266
│ └── ConfigAssist-ESP32-ESP8266.ino
├── ConfigAssist-FirmwareCheck
│ ├── ConfigAssist-FirmwareCheck.ino
│ ├── README.txt
│ ├── firmCheckESP32PMem.h
│ ├── firmCheckESP8266PMem.h
│ └── firmware
│ │ ├── ESP32
│ │ ├── FirmwareCheck1.0.1.bin
│ │ └── lastest.json
│ │ └── ESP8266
│ │ ├── FirmwareCheck1.0.1.bin
│ │ └── lastest.json
├── ConfigAssist-LargeTextArea
│ ├── ConfigAssist-LargeTextArea.ino
│ └── appPMem.h
├── ConfigAssist-LogExternal
│ └── ConfigAssist-LogExternal.ino
├── ConfigAssist-LogToFile
│ └── ConfigAssist-LogToFile.ino
├── ConfigAssist-Minimal
│ └── ConfigAssist-Minimal.ino
├── ConfigAssist-NtpTimeSync
│ ├── ConfigAssist-NtpTimeSync.ino
│ └── appPMem.h
├── ConfigAssist-Simple
│ └── ConfigAssist-Simple.ino
├── ConfigAssist-Test-Wifi
│ └── ConfigAssist-Test-Wifi.ino
├── ConfigAssist-VarAttributes
│ ├── ConfigAssist-VarAttrtibutes.ino
│ └── appPMem.h
└── ConfigAssist-WiFiAsync
│ └── ConfigAssist-WiFiAsync.ino
├── keywords.txt
├── library.json
├── library.properties
└── src
├── ConfigAssist.cpp
├── ConfigAssist.h
├── ConfigAssistHelper.cpp
├── ConfigAssistHelper.h
├── configAssistPMem.h
├── dYaml.cpp
├── dYaml.h
└── espLogger.h
/.gitignore:
--------------------------------------------------------------------------------
1 | /debug.cfg
2 | /debug_custom.json
3 | /esp32.svd
4 | .pio/
5 | partitions/
6 | test/
7 | .vscode/
8 | /platformio.ini
9 |
--------------------------------------------------------------------------------
/CHANGES.txt:
--------------------------------------------------------------------------------
1 | 2.8.7 (2024-12-17)
2 | * Added connection failover
3 | * Fixed callback with no async connection
4 | * Fix start storage called once
5 |
6 | 2.8.6 (2024-12-02)
7 | * Added WiFi async connection with WiFiResultCallback. Added example
8 | * Check connection and auto reconnect on failure
9 | * Added forced and async time synchronization
10 |
11 | 2.8.5 (2024-11-20)
12 | * Added force time synchronization.
13 | * Added read operator () and asign [] operators
14 |
15 | 2.8.4 (2024-10-19)
16 | * Load default dictionary only when setup AP
17 | * Fixed retain connections
18 |
19 | 2.8.3 (2024-04-23)
20 | * Generate config files on first run with default values.
21 | * Stream html controls to handle big text areas.
22 |
23 | 2.8.2 (2024-02-14)
24 | * Added attributes to variables (javascript, style, etc.).
25 | * Added a function to append a javascript to main page
26 |
27 | 2.8.1 (2024-02-01)
28 | * Removed regex to reduce size.
29 |
30 | 2.8.0 (2024-01-25)
31 | * Added accordion open/closed button. Fixed errors
32 |
33 | 2.7.9 (2024-01-12)
34 | * Removed Json. Fixed yaml errors
35 |
36 | 2.7.8 (2024-01-04)
37 | * Moved to yaml for definitions.
38 |
39 | 2.7.7 (2023-12-21)
40 | * Added callback function on portal updates.
41 |
42 | 2.7.6 (2023-12-15)
43 | * Added ntp time synchronization
44 |
45 | 2.7.5 (2023-11-07)
46 | * Added didplay types for seperators. Fixed errors.
47 |
48 | 2.7.3 (2023-10-24)
49 | * Added headers inside class
50 |
51 | 2.7.2 (2023-10-15)
52 | * Firmware updates over the internet.
53 |
54 | 2.7.1 (2023-10-10)
55 | * Dump to web server
56 |
57 | 2.7.0 (2023-10-10)
58 | * Enable saving wifi credentials to nvs
59 |
60 | 2.6.9 (2023-10-10)
61 | * Changed constructors, Improved log functions. Hide passwords in browser.
62 |
63 | 2.6.8 (2023-10-5)
64 | * Disable wifi-scan.time-sync,ota-update to save getMessageHtml
65 |
66 | 2.6.7 (2023-09-29)
67 | * Support OTA firmware updates with progress bar
68 |
69 | 2.6.6 (2023-09-09)
70 | * Backup and restore configuration
71 |
72 | 2.6.5 (2023-07-19)
73 | * Added set static ip to ConfigAssist-Test-Wifi.ino
74 | * Add a not found key to ini file if defined in json.
75 |
76 | 2.6.4 (2023-07-08)
77 | * Reboot confirmation using timestamp
78 |
79 | 2.6.3 (2023-06-21)
80 | * Test multiple station network connections from AP portal and show ip and signal strength
81 | after connection
82 |
83 | 2.6.2 (2023-05-15)
84 | * Allow application to logging into a file with logLevel
85 |
86 | 2.6.1 (2023-05-11)
87 | * Added function getCSS() to get ConfigAssist css on application main page
88 | * Added function getTimeSyncScript() to get ConfigAssist time sync script
89 | * Added function getMessageHtml() to get ConfigAssist simple message page
90 |
91 | 2.6.0 (2023-05-10)
92 | * Created ConfigAssist library
93 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 gemi254
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ConfigAssist
2 |
3 | A lightweight library allowing quick configuration of **esp32/esp8266** devices. **Define** application variables using a yaml text and **edit** them with a **responsive** configuration portal. Variables are updated instantly using **async get requests** and saved automatically on a ini file in local storage.
4 |
5 | ## Description
6 |
7 | **ConfigAssist** is a configuration management system for ESP-based devices (ESP32/ESP8266). It provides functionality to manage configuration files, web server operations, and handle user input on the configuration page. The class is versatile and includes support for managing network settings, reading and writing configuration files, and serving HTML forms over a web interface.
8 |
9 | **ConfigAssist** will help to automate definition of variables used in a typical **esp32/esp8266** application. It will automatically generate a web portal with edit html elements for each variable based on **yaml definition** text, allowing quick editing is value from a html page.
10 |
11 | Application variables like **Wifi ssid**, **Wifi password**, **Host Name** can be quick edited there and will be ready for use in your application. Every time a variable is changed in the web page, it will automatically updated by ConfigAssist using an **async** JavaScript request. As the user leaves or closes the page at end the data are auto saved to the ini file.
12 |
13 | ## Features
14 |
15 | * Automate **variables** definition in a typical ``ESP32/ESP8266`` project using a yaml definition description.
16 | * Configuration **portal** with various **html controls** for editing these variables from a ``web browser``.
17 | * Automatically generate an **ini** file in internal storage and auto save.
18 | * On the fly **update** values in ini file using **ajax** requests.
19 | * **Backup & Restore** device configurations.
20 | * **Wi-Fi scan** support for auto fill nearby Wi-Fi station connections.
21 | * Save **WiFi credentials** to **nvs** to retain ST connections.
22 | * **Validate** Wi-Fi station connections when connecting from AP.
23 | * Auto **synchronize** ESP32/ESP8266 internal **clock** with browser clock.
24 | * Support on the fly **firmware upgrades** (OTA).
25 | * Support automatic firmware **upgrades** over the **internet**.
26 |
27 |
28 |
29 |
30 |
31 |
32 | ## Features description
33 |
34 | **ConfigAssist** can perform a **Wifi Scan** on setup and attach a **drop down list** on the field **st_ssid** with nearby available wifi **access points**. The list will be sorted by **signal strength**, with the strongest signals to be placed first and will be refreshed every 15 seconds. Users can choose a valid nearby **ssid** from the wifi list.
35 |
36 | **Station** Wifi **connections** can be **validated** during setup with ``Test connection`` link available on each **st_ssid** field. The device will be switched to **WIFI_AP_STA** and **ConfigAssist** will try to test the Station connection with **Wifi ssid**, **Wifi password** entered without disconnecting from the Access Point. If the connection is successful the Station ip address and signal strength will be displayed.
37 |
38 | **WiFi credentials** can also be saved to **nvs** to retain ST connections. On **factory defaults** the nvs will be not cleared and the ST connection will be still available.
39 | You can use the command ``http://ip/cfg?_CLEAR=1`` to clear nvs.
40 | Set **CA_USE_PERSIST_CON** to 1 in ``ConfigAssist.h`` to use this feature.
41 |
42 | **ConfigAssist** can also check and synchronize the internal **clock** of ESP device with the browser time if needed. So even if no internet connection (AP mode) and no **npt** server is available the device will get the correct time. If **CA_TIMEZONE_KEY** string exists in variables it will be used to set the device time zone string. If not it will use browser offset.
43 |
44 | **ConfigAssist** can add web based **OTA** updates to your ESP32/ESP8266 projects. With the button **Upgrade** you can upload a firmware file (*.bin) from you pc and perform a **firmware upgrade** to the device.
45 |
46 | **ConfigAssist** can also pefrom **Firmware upgrades** over **internet**. It will compare the currnet firmware version of the device with a remote firmware stored in a **web site** location. If there is a new firmware it will automatically download it and pefrom the upgrade.
47 |
48 | Check the FirmwareCheck example for more details.
49 |
50 | These features can be disabled to save memory by setting 1 / 0 the lines **CA_USE_WIFISCAN**, **CA_USE_TESTWIFI**, **CA_USE_TIMESYNC**, **CA_USE_OTAUPLOAD**, and **CA_USE_FIMRMCHECK** in ``ConfigAssist.h``.
51 |
52 | You can also use compiler flags to enable / disable theese features
53 | ```
54 | build_flags = -DCA_USE_LITTLEFS ; Use littlefs remove for spiffs
55 | -DLOGGER_LOG_LEVEL=5
56 | -DCA_USE_WIFISCAN=1
57 | -DCA_USE_TESTWIFI=1
58 | -DCA_USE_TIMESYNC=1
59 | -DCA_USE_OTAUPLOAD=1
60 | -DCA_USE_FIMRMCHECK=1
61 | ```
62 | Device's configuration ``(*.ini files)`` can be downloaded with the **Backup** button and can be restored later with the **Restore** button.
63 |
64 | You can use the command ``http://ip/cfg?_RST=1`` to manually clear the ini file and load defaults.
65 |
66 | ## Configuration variables
67 |
68 | Variables **descriptions** and **default values** are based on a **text description** in yaml format that acts as a template defining the **type**, **label** and extra **info** of each variable.
69 |
70 | All config variables must be defined there describing the **variable type**, **default value** and the **label** that will be displayed to the user. It can also include and some **attributes** in case of special variables like **datalist** for list box, min, max, step for **input number** etc.
71 | ```
72 | Wifi settings:
73 | - st_ssid:
74 | label: Name for WLAN
75 | default: ''
76 | ```
77 | A simple html page will be generated by **ConfigAssist** allowing quick editing these variables from a web Browser with a connection to the device. While editing the variables they will be **instantly** available to the application and will be automatically saved.
78 |
79 | Application variables can be used in code with operator **()** i.e. ```conf('variable')```. The configuration data will be stored in the **SPIFFS** as an **ini file** (Plain Text) and will be automatically loaded on each reboot.
80 |
81 | ## How it works
82 |
83 | On first run when no data (**ini file**) is present in local storage, **ConfigAssist** will start an **Access Point** and load the default yaml dictionary with variable definitions that will be edited. It will then generate an html page with html controls allowing data to be edited from the connected devices.
84 |
85 | On each **change** in the html page data will be **updated** and will be available immediately to the application. The data will be saved automatically on local storage when the user finishes editing. If the configuration file is valid during next boot, **yaml dictionary** will not be loaded reducing memory consumption and speeding up the whole process. Note that if data is not changed **ConfigAssist** will not re-save the file.
86 |
87 | ConfigAssist uses **c++ vectors** to dynamically allocate and store variables and **binary search** for speeding the access process.
88 |
89 | ## How to use variables
90 |
91 | **ConfigAssist** consists of single file "ConfigAssist.h" that must be included in your application
92 | The application variables can be used directly by accessing the **class** itself by operator **())**
93 | i.e.
94 |
95 | + `String ssid = conf("st_ssid");`
96 | + `bool debug = conf("debug").toInt();`
97 | + `int pinNo = conf("st_ssid").toInt();`
98 | + `digitalWrite(conf("led_buildin").toInt(), 0)`;
99 | + `float float_value = atof(conf("float_value").c_str());`
100 |
101 | Also values can be assigned dynamically with operator **[]**
102 |
103 | + `conf["st_ssid"] = "TestWifi";`
104 | + `conf["debug"] = 1;`
105 | + `conf["float_value"] = 12.3;`
106 |
107 |
108 | ## Variables definition with YAML dictionary
109 |
110 | In your application sketch file you must define a yaml dictionary that includes all the information needed for the html edit form to be generated. Each variable will be displayed on edit page with the order defined in the yaml file. See example below...
111 |
112 |
113 | + If you use keywords `name, default` an **edit box** will be generated to edit the variable. Add `attribs` keywords to specify min, max, step for a numeric field.
114 | + If you keyword name ends with ``_pass`` (or ``_pass`` and a number i.e``_pass1``) a **password field** will be used. See **CA_ST_PASSWD_KEY** definition.
115 | + If you use keyword `checked` instead of `default` a Boolean value will be used that will be edited by a **check box**
116 | + You can combine keywords `default` with `options` in order to use a select list that will be edited by a **drop list**.
117 | - The `options` field must contain a comma separated list of values and can be enclosed by single quotes.
118 | - The `options` field can contains **option names**, **values pairs** delimited with ':' for example 'AllOpen':'0', 'AllClosed':'1' etc.
119 |
120 | + You can combine keywords `default` with `range` in order to use a value that will be edited by a **input range**.
121 | - The `range` field must contain a comma separated list of `min, max, step` and can be enclosed by single quotes.
122 | + You can combine keywords `default` with `datalist` in order to use a value that will be edited by a **combo box**.
123 | - The `datalist` field must contain a comma or line feed separated list of default values for drop down list.
124 | + You can combine keywords `default` with `file` in order to use a small text be edited by a **text area**.
125 | - The `file` field must contain a valid file path that the text will be saved to. The `default` keyword can also be used to define a default value.
126 |
127 | + All vars can have the keyword `attribs` to specify special attributes like javaScript, style for this field.
128 | - For example `attribs: onChange = "this.style.color = 'red'"; `
129 | - You can use `setSubScript` function to add an init java script to main page.
130 |
131 | Check ConfigAssist-VarAttributes in ``examples/`` folder for more details.
132 |
133 |
134 | A **separator title** can also be used to group configuration values under a specific title.
135 |
136 |
137 |
138 |
139 | Seperators can be opened and closed when click on their title. You can define the initial state by using **setDisplayType** function.
140 |
141 | Use **AllOpen** to display opened tabs, **AllClosed** to display seperator titles only and **Accordion** to close all but not current tab.
142 | ```
143 | // Set the display type
144 | conf.setDisplayType(ConfigAssistDisplayType::Accordion);
145 | ```
146 |
147 | Version 2.7.8 now uses yaml instead of json descriptions to save space and increase speed
148 | See direct-yaml for details.
149 |
150 | If you want to convert your existing configuration from JSON to YAML
151 | download version
152 |
153 | ConfigAssist v2.7.8
154 |
155 | comment at ConfigAssist.h line 7
156 | ```
157 | #define CA_USE_YAML // Comment to use JSON
158 | ```
159 | Compile the JSON version and add a yaml dump handler.
160 | ```
161 | server.on("/yaml", []() { // Append yaml dump handler
162 | conf.dumpYaml(&server);
163 | });
164 | ```
165 | Upload and visit ``http://ip/yaml`` to copy your configuration in yaml format.
166 |
167 | ## Sample variables definition text
168 | ```
169 | const char* VARIABLES_DEF_YAML PROGMEM = R"~(
170 | Wifi settings:
171 | - st_ssid:
172 | label: Name for WLAN
173 | default: ''
174 | - st_pass:
175 | label: Password for WLAN
176 | default: ''
177 | - host_name:
178 | label: >-
179 | Host name to use for MDNS and AP {mac} will be replaced with device's mac
180 | id
181 | default: configAssist_{mac}
182 |
183 | Application settings:
184 | - app_name:
185 | label: Name your application
186 | default: ConfigAssistDemo
187 | - led_buildin:
188 | label: Enter the pin that the build in led is connected. Leave blank for auto.
189 | attribs: "min='2' max='23' step='1'"
190 | default: 2
191 |
192 | ConfigAssist settings:
193 | - display_style:
194 | label: Choose how the config sections are displayed. Must reboot to apply
195 | options:
196 | - AllOpen: 0
197 | - AllClosed: 1
198 | - Accordion : 2
199 | - AccordionToggleClosed : 3
200 | default: AccordionToggleClosed
201 |
202 | Other settings:
203 | - float_val:
204 | label: Enter a float val
205 | default: 3.14159
206 | attribs: min="2.0" max="5" step=".001"
207 | - debug:
208 | label: Check to enable debug
209 | checked: False
210 | - sensor_type:
211 | label: Enter the sensor type
212 | options: 'BMP280', 'DHT12', 'DHT21', 'DHT22'
213 | default: DHT22
214 | - refresh_rate:
215 | label: Enter the sensor update refresh rate
216 | range: 10, 50, 1
217 | default: 30
218 | - time_zone:
219 | label: Needs to be a valid time zone string
220 | default: EET-2EEST,M3.5.0/3,M10.5.0/4
221 | datalist:
222 | - Etc/GMT,GMT0
223 | - Etc/GMT-0,GMT0
224 | - Etc/GMT-1,<+01>-1
225 | - cal_data:
226 | label: Enter data for 2 Point calibration.Data will be saved to /calibration.ini
227 | file: "/calibration.ini"
228 | default:
229 | X1=222, Y1=1.22
230 | X2=900, Y2=3.24
231 | )~";
232 | ```
233 |
234 | ## Project definitions in your main app
235 |
236 | + include the **ConfigAssist** class
237 | - `#include //ConfigAssist class`
238 |
239 | + Define your static instance with **defaults**
240 | - `ConfigAssist conf;`
241 |
242 | + if you want to use a different external **ini file name**
243 | - `ConfigAssist conf(INI_FILE);`
244 |
245 | + if you want to use a different external **ini file name** and **yaml description**
246 | - `ConfigAssist conf(INI_FILE, VARIABLES_DEF_YAML); // ConfigAssist with custom name & dictionary`
247 |
248 | + if you want to use a different external **ini file name** and **yaml description** disabled
249 | - `ConfigAssist conf(INI_FILE, NULL); // ConfigAssist with custom ini name & dictionary disabled`
250 |
251 | ## Call back functions
252 | You can define a call back function wich will be called when the portal changes a value.
253 | This function will be called each time a value is changed from the portal with the value name as a parameter.
254 | ```
255 |
256 | // Will be called when portal is updating a key
257 | void onDataChanged(String key){
258 | LOG_I("Data changed, key:%s, val: %s \n", key.c_str(), conf(key).c_str());
259 | }
260 |
261 | // Setup call back function
262 | conf.setRemotUpdateCallback(onDataChanged);
263 |
264 | ```
265 |
266 | ## WIFI Access point handlers
267 |
268 | **ConfigAssist** must be initialized with a pointer to a web server to automatically handle AP form requests.
269 | Setup will add web handlers /cfg, /scan, to the server and if apEnable = true will enable Access Point.
270 | ```
271 | conf.setup(server, /*Start AP*/ true);
272 | or
273 | conf.setupConfigPortal(server, true);
274 | ```
275 | You can add /cfg handler to your application after connecting the device to the internet.
276 | Editing config will be enabled for station users.
277 |
278 | ```
279 | // ConfigAssist will register handlers to the web server
280 | // so config can be edited.
281 | conf.setupConfigPortalHandlers(server);
282 | ```
283 | ## Connect the WiFi using **ConfigAsistHelper**
284 | In order to simplify the proccess of connect to WiFi and set static ip address use the **ConfigAsistHelper class**. It will connect the WiFi using credentials contained in a ConfigAssist class. It will search for variables ending with **CA_ST_SSID_KEY** for ssid and **CA_ST_PASSWD_KEY** for passwords.
285 | For example variables like..
286 | ```
287 | st_ssid, st_pass,
288 | station_ssid, station_pass
289 | ```
290 | It can also use variables like..
291 | ```
292 | st_ssid1, st_pass1,
293 | st_ssid2, st_pass2
294 | ```
295 | for failover connections.
296 |
297 | If a variable found ending with **CA_ST_STATICIP_KEY** it will automatically set static ip.
298 |
299 | To use **ConfigAsistHelper**
300 | ```
301 | // Define a ConfigAssist helper class with a ConfigAssist conf
302 | // containig credentials
303 | ConfigAssistHelper confHelper(conf);
304 | ```
305 |
306 | ```
307 | // Connect to any available network
308 | // Wait for connection or TimeOut
309 | bool bConn = confHelper.connectToNetwork(15000 /*Timeout ms*/, conf("led_buildin").toInt() /*Key containig internal led*/);
310 | ```
311 |
312 | ```
313 | // Connect to any available network async
314 | // It will not wait to connect but will send a connection result
315 | // Set Wi-Fi credentials from config and start connection process
316 | confHelper.connectToNetworkAsync(15000, 13, [](ConfigAssistHelper::WiFiResult result, const String& msg) {
317 | switch (result) {
318 | case ConfigAssistHelper::WiFiResult::SUCCESS:
319 | LOG_D("Connected to Wi-Fi! IP: %s\n", msg.c_str());
320 | break;
321 |
322 | case ConfigAssistHelper::WiFiResult::INVALID_CREDENTIALS:
323 | LOG_D("Invalid credentials: %s\n", msg.c_str());
324 | break;
325 |
326 | case ConfigAssistHelper::WiFiResult::CONNECTION_TIMEOUT:
327 | LOG_D("Connection fail: %s\n", msg.c_str());
328 | break;
329 |
330 | case ConfigAssistHelper::WiFiResult::DISCONNECTION_ERROR:
331 | LOG_D("Disconnect: %s\n", msg.c_str());
332 | break;
333 |
334 | default:
335 | LOG_D("Unknown result: %s\n", msg.c_str());
336 | break;
337 | }
338 | });
339 | ```
340 |
341 | ## Synchronize time using **ConfigAsistHelper**
342 | ConfigAssist can synchronize device's time with a ntp server using **ConfigAsistHelper**.
343 | Variables ending with **CA_NTPSYNC_KEY** for example **ntp_server1**, **ntp_server2**, **ntp_server3**
344 | will be used as ntp servers.
345 | The current timezone for the device will be set automatically using **CA_TIMEZONE_KEY** for example **time_zone**
346 |
347 | Just define **ntp_server1**, **ntp_server2**, **ntp_server3** and **time_zone** settings in your config and call **syncTime** with timeout ms to wait until time is synchronized. Use force = true to reset clock and wait the time to be synchronized.
348 | ```
349 | - ntp_server1:
350 | label: Time server to sync time1
351 | default: "europe.pool.ntp.org"
352 | - ntp_server2:
353 | label: Time server to sync time2
354 | default: "time.windows.com"
355 | - ntp_server3:
356 | label: Time server to sync time3
357 | default: "pool.ntp.org"
358 |
359 | // Setup time synchronization
360 | // Wait max 10 sec for sync
361 | confHelper.syncTime(10000);
362 |
363 | // Force time synchronization,
364 | // Clock will be reseted and wait for max 20 sec to sync
365 | // If fail clock will be restored
366 | confHelper.syncTime(20000, true);
367 | or
368 | // Sync time, force to reset clock, async to not wait for sync
369 | // In asynchronous mode, if time synchronization fails, no restoration of the clock occurs.
370 | confHelper.syncTimeAsync(20000, true);
371 |
372 | ```
373 |
374 | ## Setup function
375 | ```
376 | void setup()
377 |
378 | // Setup led on empty string
379 | if(conf("led_buildin")=="") conf.put("led_buildin", LED_BUILTIN);
380 | // Or
381 | if(conf("led_buildin")=="") conf["led_buildin"] = LED_BUILTIN;
382 |
383 | // Connect to any available network with timeout 1500 and led pin on led_buildin variable
384 | bool bConn = confHelper.connectToNetwork(15000, conf("led_buildin").toInt());
385 |
386 | // Append config assist handlers to web server, setup ap on no connection
387 | conf.setup(server, !bConn);
388 | if(!bConn) LOG_E("Connect failed.\n");
389 |
390 | ```
391 |
392 | ## Ini files
393 | **ConfigAssist** can also used to quick generate and store ini files.
394 | Just call the class constructor with a filename to be saved and null to disable dictionary.
395 | ```
396 | ConfigAssist info("/info.ini", NULL);
397 | ```
398 | and add the parameters to be stored with
399 | ```
400 | info.put("var1", "test1", true);
401 | or
402 | info["var1"] = "test1";
403 |
404 | info.saveConfigFile();
405 | ```
406 |
407 | ## Logging to a file
408 | **ConfigAssist** can redirect serial print functions to a file in a spiffs and a **Debug log** can be generated.
409 | In your application you use **LOG_E**, **LOG_W**, **LOG_I**, **LOG_D** macros instead of **Serial.prinf**
410 | to print your messages. **ConfigAssist** can record these messages with **timestamps** to a file.
411 |
412 | + define **ConfigAssist** log mode
413 | Define the log level (Error = 1 .. Verbose = 5)
414 | ```
415 | #define LOGGER_LOG_LEVEL 5 // Errors & Warnings & Info & Debug & Verbose
416 | ```
417 |
418 | + if you want to enable serial print to a log file use..
419 | ```
420 | //Enable ConfigAssist logging to file
421 | #define LOGGER_LOG_MODE 2 // Log to file
422 |
423 | //Define the log filename
424 | #define LOGGER_LOG_FILENAME "/log1"
425 | ```
426 |
427 | + You can also use your own log_printf function by setting log mode to 3
428 | ```
429 | #define LOGGER_LOG_MODE 3 // External log_printf function
430 | ```
431 |
432 | Check ConfigAssist-LogExternal in ``examples/`` folder.
433 |
434 | ## Compile
435 | Download library files and place them on ./libraries directory under ArduinoProjects
436 | Then include the **ConfigAssist.h** in your application and compile..
437 |
438 | + compile for arduino-esp3 or arduino-esp8266.
439 | + To use Persistent ST connections On ESP8266 devices you must install **Preferences** library to provide ESP32-compatible Preferences API using LittleFS
440 | + if your variables exceed **CA_MAX_PARAMS** increase this value in class header.
441 |
442 | You can remove old **ini** config file by calling `conf.deleteConfig();` in your setup function.
443 | See **ConfigAssist-ESP32-ESP8266.ino** line:210
444 |
445 | ###### If you get compilation errors on arduino-esp32 you need to update your arduino-esp32 library in the IDE using Boards Manager
446 |
447 | ## Other examples
448 | You can see an advanced example of **ConfigAssist** usage on **PlantStatus** a plant monitoring and logging application
449 |
--------------------------------------------------------------------------------
/docs/config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/f7830b0e43629fceadb76a4bd6e2f7e38cb363a1/docs/config.png
--------------------------------------------------------------------------------
/docs/config_colapsed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/f7830b0e43629fceadb76a4bd6e2f7e38cb363a1/docs/config_colapsed.png
--------------------------------------------------------------------------------
/examples/ConfigAssist-Dynamic/ConfigAssist-Dynamic.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class definition
2 |
3 | // Create a config class with an ini filename for storage
4 | //Start storage and load config
5 | ConfigAssist config("/info1.ini");
6 | bool reset = false;
7 | void setup() {
8 | // put your setup code here, to run once:
9 |
10 | Serial.begin(115200);
11 | Serial.print("\n\n\n\n");
12 | Serial.flush();
13 |
14 | LOG_I("Starting..\n");
15 |
16 | if(reset){
17 | config.deleteConfig(); // Remove ini file and re-built
18 | config.clear(); // Clear loaded keys
19 | }
20 | // Dict is disabled, Ini file not found
21 | if(!config.confExists()){
22 | String textDict="YAML DICT: \n";
23 | for(int i=0; i<10; ++i){
24 | textDict += " - var_"+ String(i) +":\n";
25 | textDict += " default: "+ String(i) +"\n";
26 | }
27 | LOG_I("Generated yaml:\n %s\n",textDict.c_str());
28 |
29 | // Build ini file from textDict
30 | config.setDictStr(textDict.c_str(), true);
31 | LOG_I("Config valid: %i\n",config.valid());
32 | // Save keys & values into ini file
33 | config.saveConfigFile();
34 | config.dump();
35 | }else{ // Ini file is valid, display the values
36 | config.dump();
37 | }
38 | }
39 |
40 | void loop() {
41 | // put your main code here, to run repeatedly:
42 | }
43 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-ESP32-ESP8266/ConfigAssist-ESP32-ESP8266.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class
2 | #include // Config assist helper class
3 |
4 | #if defined(ESP32)
5 | WebServer server(80);
6 | #else
7 | ESP8266WebServer server(80);
8 | #endif
9 |
10 | #ifndef LED_BUILTIN
11 | #define LED_BUILTIN 22
12 | #endif
13 |
14 | #define INI_FILE "/ConfigAssistDemo.ini" // Define SPIFFS storage file
15 |
16 | unsigned long pingMillis = millis(); // Ping
17 |
18 | // Default application config dictionary
19 | // Modify the file with the params for you application
20 | // Then you can use then then by val = config[name];
21 | const char* VARIABLES_DEF_YAML PROGMEM = R"~(
22 | Wifi settings:
23 | - st_ssid:
24 | label: Name for WLAN
25 | - st_pass:
26 | label: Password for WLAN
27 | - host_name:
28 | label: Host name to use for MDNS and AP
29 | {mac} will be replaced with device's mac id
30 | default: configAssist_{mac}
31 |
32 | Application settings:
33 | - app_name:
34 | label: Name your application
35 | default: ConfigAssistDemo
36 | - led_buildin:
37 | label: Enter the pin that the build in led is connected.
38 | Leave blank for auto.
39 | attribs: "min='2' max='23' step='1'"
40 |
41 | ConfigAssist settings:
42 | - display_style:
43 | label: Choose how the config sections are displayed.
44 | Must reboot to apply
45 | options:
46 | - AllOpen: 0
47 | - AllClosed: 1
48 | - Accordion : 2
49 | - AccordionToggleClosed : 3
50 | default: AccordionToggleClosed
51 | - work_mode:
52 | label: Application Work mode. Must reboot to apply
53 | options: "'MeasureUpload': '0' ,'MeasureBatchUpload':'1', 'MeasureUploadSleep':'2', 'MeasureBatchUploadSleep':'3', 'MeasureTimeoutUploadSleep':'4'"
54 | default: 2
55 |
56 | Other settings:
57 | - float_val:
58 | label: Enter a float val
59 | default: 3.14159
60 | attribs: min="2.0" max="5" step=".001"
61 | - debug:
62 | label: Check to enable debug
63 | checked: False
64 | - sensor_type:
65 | label: Enter the sensor type
66 | options: 'BMP280', 'DHT12', 'DHT21', 'DHT22'
67 | default: DHT22
68 | - refresh_rate:
69 | label: Enter the sensor update refresh rate
70 | range: 10, 50, 1
71 | default: 30
72 | - time_zone:
73 | label: Needs to be a valid time zone string
74 | default: EET-2EEST,M3.5.0/3,M10.5.0/4
75 | datalist:
76 | - Etc/GMT,GMT0
77 | - Etc/GMT-0,GMT0
78 | - Etc/GMT-1,<+01>-1
79 | - Etc/GMT-2,<+02>-2
80 | - Etc/GMT-3,<+03>-3
81 | - Etc/GMT-4,<+04>-4
82 | - Etc/GMT-5,<+05>-5
83 | - Etc/GMT-6,<+06>-6
84 | - Etc/GMT-7,<+07>-7
85 | - Etc/GMT-8,<+08>-8
86 | - Etc/GMT-9,<+09>-9
87 | - Etc/GMT-10,<+10>-10
88 | - Etc/GMT-11,<+11>-11
89 | - Etc/GMT-12,<+12>-12
90 | - Etc/GMT-13,<+13>-13
91 | - Etc/GMT-14,<+14>-14
92 | - Etc/GMT0,GMT0
93 | - Etc/GMT+0,GMT0
94 | - Etc/GMT+1,<-01>1
95 | - Etc/GMT+2,<-02>2
96 | - Etc/GMT+3,<-03>3
97 | - Etc/GMT+4,<-04>4
98 | - Etc/GMT+5,<-05>5
99 | - Etc/GMT+6,<-06>6
100 | - Etc/GMT+7,<-07>7
101 | - Etc/GMT+8,<-08>8
102 | - Etc/GMT+9,<-09>9
103 | - Etc/GMT+10,<-10>10
104 | - Etc/GMT+11,<-11>11
105 | - Etc/GMT+12,<-12>12
106 | - cal_data:
107 | label: Enter data for 2 Point calibration.
108 | Data will be saved to /calibration.ini
109 | file: "/calibration.ini"
110 | default:
111 | X1=222, Y1=1.22
112 | X2=900, Y2=3.24
113 | )~";
114 |
115 | ConfigAssist conf(INI_FILE, VARIABLES_DEF_YAML); // Config assist class
116 | ConfigAssistHelper confHelper(conf); // Define a ConfigAssist helper for managing connection
117 | // Setup led
118 | String s = (conf("led_buildin") == "") ? conf["led_buildin"] = LED_BUILTIN : "";
119 |
120 | // Print memory info
121 | void debugMemory(const char* caller) {
122 | #if defined(ESP32)
123 | LOG_I("%s > Free: heap %u, block: %u, pSRAM %u\n", caller, ESP.getFreeHeap(), heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), ESP.getFreePsram());
124 | #else
125 | LOG_I("%s > Free: heap %u\n", caller, ESP.getFreeHeap());
126 | #endif
127 | }
128 |
129 | // List the storage file system
130 | void ListDir(const char * dirname) {
131 | LOG_I("Listing directory: %s\n", dirname);
132 | // List details of files on file system
133 | File root = STORAGE.open(dirname, "r");
134 | File file = root.openNextFile();
135 | while (file) {
136 | #if defined(ESP32)
137 | LOG_I("File: %s, size: %u B\n", file.path(), file.size());
138 | #else
139 | LOG_I("File: %s, size: %u B\n", file.fullName(), file.size());
140 | #endif
141 | file = root.openNextFile();
142 | }
143 | Serial.println("");
144 | }
145 |
146 | // Handler function for Home page
147 | void handleRoot() {
148 | String out("
Hello from {name}
");
149 | out += "
Device time: " + conf.getLocalTime() +"
";
150 | out += "Edit config";
151 | conf["refresh_rate"] = conf("refresh_rate").toInt() + 1;
152 | #if defined(ESP32)
153 | out.replace("{name}", "ESP32");
154 | #else
155 | out.replace("{name}", "ESP8266!");
156 | #endif
157 | #if (CA_USE_TIMESYNC)
158 | out += "";
159 | #endif
160 | server.send(200, "text/html", out);
161 | }
162 |
163 | // Handler for page not found
164 | void handleNotFound() {
165 | String message = "File Not Found\n\n";
166 | message += "URI: ";
167 | message += server.uri();
168 | message += "\nMethod: ";
169 | message += (server.method() == HTTP_GET) ? "GET" : "POST";
170 | message += "\nArguments: ";
171 | message += server.args();
172 | message += "\n";
173 | for (uint8_t i = 0; i < server.args(); i++) {
174 | message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
175 | }
176 | server.send(404, "text/plain", message);
177 | }
178 |
179 | // CallBack function when conf remotely changes
180 | void onDataChanged(String key){
181 | LOG_I("Data changed: %s = %s \n", key.c_str(), conf(key).c_str());
182 | if(key == "display_style")
183 | conf.setDisplayType((ConfigAssistDisplayType)conf("display_style").toInt());
184 |
185 | }
186 | // Setup function
187 | void setup(void) {
188 | Serial.begin(115200);
189 | Serial.print("\n\n\n\n");
190 | Serial.flush();
191 |
192 | LOG_I("Starting..\n");
193 | debugMemory("setup");
194 |
195 | //ListDir("/");
196 |
197 | //conf.deleteConfig(); // Uncomment to remove old ini file and re-built it fron dictionary
198 |
199 | // Register handlers for web server
200 | server.on("/", handleRoot); // Add root handler
201 | server.on("/d", []() { // Append dump handler
202 | conf.dump(&server);
203 | });
204 |
205 | server.onNotFound(handleNotFound); // Append not found handler
206 |
207 | debugMemory("Loaded config");
208 |
209 | // Will be called when portal is updating a key
210 | conf.setRemotUpdateCallback(onDataChanged);
211 |
212 | WiFi.setAutoConnect(false);
213 | WiFi.setAutoReconnect(false);
214 |
215 | // Connect to any available network and connect or timeout
216 | bool bConn = confHelper.connectToNetwork(15000, conf("led_buildin").toInt());
217 |
218 | // Append config assist handlers to web server, setup ap on no connection
219 | conf.setup(server, !bConn);
220 | if(!bConn) LOG_E("Connect failed.\n");
221 | else confHelper.startMDNS();
222 |
223 | // Get int/bool value
224 | bool debug = conf("debug").toInt();
225 | LOG_I("Boolean value: %i\n", debug);
226 |
227 | // Get float value
228 | float float_value = conf("float_val").toFloat();
229 | LOG_I("Float value: %1.5f\n", float_value);
230 |
231 | // Set the defined display type
232 | conf.setDisplayType((ConfigAssistDisplayType)conf("display_style").toInt());
233 |
234 | server.begin();
235 | LOG_I("HTTP server started, display type: %s\n", conf("display_style").c_str());
236 |
237 | // On the fly generate an ini info file on SPIFFS
238 | {
239 | if(debug) STORAGE.remove("/info.ini");
240 | ConfigAssist info("/info.ini");
241 | // Add a key even if not exists. It will be not editable
242 | if(!info.valid()){
243 | LOG_D("Info file not exists\n");
244 | info["bootCnt"] = 1;
245 | info["lastRSSI"] = WiFi.RSSI();
246 | //info.put("bootCnt", 1, true);
247 | //info.put("lastRSSI", WiFi.RSSI(), true);
248 | }else{
249 | LOG_I("Info file: bootCnt: %s, lastRSSI: %s\n", info("bootCnt").c_str(), info("lastRSSI").c_str() );
250 | info["bootCnt"] = info("bootCnt").toInt() + 1;
251 | info["lastRSSI"] = WiFi.RSSI();
252 | //info.put("bootCnt", info["bootCnt"].toInt() + 1, true);
253 | //info.put("lastRSSI", WiFi.RSSI(), true);
254 | }
255 | info.saveConfigFile();
256 | info.dump();
257 | }
258 | }
259 |
260 | // App main loop
261 | void loop(void) {
262 | server.handleClient();
263 | confHelper.loop();
264 |
265 | // Display info
266 | if (millis() - pingMillis >= 10000){
267 | // if debug is enabled in config display memory debug messages
268 | if(conf("debug").toInt()) debugMemory("Loop");
269 | pingMillis = millis();
270 | }
271 |
272 | // Allow the cpu to switch to other tasks
273 | delay(2);
274 | }
275 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/ConfigAssist-FirmwareCheck.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class
2 | #include // Config assist helper class
3 |
4 | #if defined(ESP32)
5 | #include "firmCheckESP32PMem.h"
6 | WebServer server(80);
7 | #else
8 | #include "firmCheckESP8266PMem.h"
9 | ESP8266WebServer server(80);
10 | #endif
11 |
12 | #ifndef LED_BUILTIN
13 | #define LED_BUILTIN 22
14 | #endif
15 | #define APP_VER "1.1" // Application version
16 | #define INI_FILE "/FirmwareCheck.ini" // Define SPIFFS storage file
17 |
18 | // Config class
19 | ConfigAssist conf(INI_FILE, VARIABLES_DEF_YAML);
20 | // Define a ConfigAssist helper
21 | ConfigAssistHelper confHelper(conf);
22 |
23 |
24 | String hostName; // Default Host name
25 |
26 | // Handler function for Home page
27 | void handleRoot() {
28 |
29 | String out("
Hello from {name}
");
30 | out += "
Device time: " + conf.getLocalTime() +"
";
31 | out += "Edit config";
32 |
33 | #if defined(ESP32)
34 | out.replace("{name}", "ESP32");
35 | #else
36 | out.replace("{name}", "ESP8266!");
37 | #endif
38 | #if (CA_USE_TIMESYNC)
39 | out += "";
40 | #endif
41 | server.send(200, "text/html", out);
42 | }
43 |
44 | // Handler for page not found
45 | void handleNotFound() {
46 | String message = "File Not Found\n\n";
47 | message += "URI: ";
48 | message += server.uri();
49 | message += "\nMethod: ";
50 | message += (server.method() == HTTP_GET) ? "GET" : "POST";
51 | message += "\nArguments: ";
52 | message += server.args();
53 | message += "\n";
54 | for (uint8_t i = 0; i < server.args(); i++) {
55 | message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
56 | }
57 | server.send(404, "text/plain", message);
58 | }
59 |
60 | // Setup function
61 | void setup(void) {
62 |
63 | Serial.begin(115200);
64 | Serial.print("\n\n\n\n");
65 | Serial.flush();
66 |
67 | LOG_I("Starting.. ver: %s\n", APP_VER);
68 | LOG_I("WiFi mode: %i\n", (int)WiFi.getMode());
69 |
70 | if(false) conf.deleteConfig(); // Set to true ro remove old ini file and re-built it fron dictionary
71 |
72 | // Register handlers for web server
73 | server.on("/", handleRoot);
74 | server.on("/d", []() { // Append dump handler
75 | conf.dump(&server);
76 | });
77 | server.onNotFound(handleNotFound); // Append not found handler
78 |
79 | // Connect to any available network
80 | bool bConn = confHelper.connectToNetwork(15000, LED_BUILTIN);
81 |
82 | // Append config assist handlers to web server, setup ap on no connection
83 | conf.setup(server, !bConn);
84 | if(!bConn){
85 | LOG_E("Connect failed.\n");
86 | }else{
87 | confHelper.startMDNS();
88 | }
89 |
90 | // Start web server
91 | server.begin();
92 | LOG_I("HTTP server started\n");
93 | }
94 |
95 | // App main loop
96 | void loop(void) {
97 | server.handleClient();
98 | confHelper.loop();
99 | // Allow the cpu to switch to other tasks
100 | delay(2);
101 | }
102 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/README.txt:
--------------------------------------------------------------------------------
1 | This is an Example hosting firmware updates of an esp application on a remote web server (like github.com) and
2 | perform automatic check and upgrade when the version is changed.
3 |
4 | The firmware version of the device running ConfigAssist is compared with the latest version stored in the remote web server.
5 | If there is a change an `Upgrade firmware` button will be displayed in order to perform an automatic firware upgrade to
6 | the newest version.
7 |
8 | How to use this feature..
9 | Bellow is the steps needed to use firmware check and upgrade using ConfigAssist. This example
10 | is using github.com to host the new firmware.
11 |
12 | !. Create a repo in github.com with your project.
13 | * For example `https://github.com/gemi254/ControlAssist-ESP32-ESP8266`
14 |
15 | 2. Create a sub folder to store your firmware information and the binary file.
16 | * For example `https://github.com/gemi254/ControlAssist-ESP32-ESP8266/firmware`
17 |
18 | 3. Create e file named "latest.json" inside your firmware folder with firmware information in json format.
19 | * Inside latest.json put the latest version number, a short description, and a link to the firmware file.
20 | * For example `https://github.com/gemi254/ControlAssist-ESP32-ESP8266/firmware/latest.json`
21 | contents:
22 | {
23 | "ver" : "1.0.1",
24 | "url" : "https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/main/examples/ConfigAssist-FirmwareCheck/firmware/FirmwareCheck1.0.1.bin",
25 | "descr": "A new firmware v1.0.1 with bug fixes and improvements."
26 | }
27 |
28 | 4. Set the default value of variable ``firmware_url``.
29 | * In you project at your VARIABLES_DEF_YAML (ConfigAssist-FirmwareCheck.ino line 55).
30 |
31 | 6. In you project, define your current firmware version.
32 | * char FIRMWARE_VERSION[] = "1.0.0";
33 |
34 | 7. Compile and rename the firmware file.
35 | * firmware.bin -> FirmwareCheck1.1.1.bin
36 |
37 | 8. Upload the firmware to github at url defined in latest.json
38 |
39 | 9. By pressing `Firmware` button in config page, ConfigAssist will compare current version with the version stored in github.com
40 | If newer version exists it will show a button `Upgrade Firmware` that will automatically perform a firmware upgrade with
41 | the latest firmware stored in github.com
42 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/firmCheckESP32PMem.h:
--------------------------------------------------------------------------------
1 | const char* VARIABLES_DEF_YAML PROGMEM = R"~(
2 | Wifi settings:
3 | - st_ssid:
4 | label: Name for WLAN
5 | - st_pass:
6 | label: Password for WLAN
7 | - host_name:
8 | label: >-
9 | Host name to use for MDNS and AP
10 | {mac} will be replaced with device's mac id
11 | default: configAssist_{mac}
12 |
13 | Application settings:
14 | - app_name:
15 | label: Name your application
16 | default: FirmwareCheck
17 | - firmware_url:
18 | label: Firmware upgrade url with version and info
19 | default: >-
20 | https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/main/examples/ConfigAssist-FirmwareCheck/firmware/ESP32/lastest.json
21 | - time_zone:
22 | label: Needs to be a valid time zone string
23 | default: EET-2EEST,M3.5.0/3,M10.5.0/4
24 | datalist:
25 | - Etc/GMT,GMT0
26 | - Etc/GMT-0,GMT0
27 | - Etc/GMT-1,<+01>-1
28 | - Etc/GMT-2,<+02>-2
29 | - Etc/GMT-3,<+03>-3
30 | - Etc/GMT-4,<+04>-4
31 | - Etc/GMT-5,<+05>-5
32 | - Etc/GMT-6,<+06>-6
33 | - Etc/GMT-7,<+07>-7
34 | - Etc/GMT-8,<+08>-8
35 | - Etc/GMT-9,<+09>-9
36 | - Etc/GMT-10,<+10>-10
37 | - Etc/GMT-11,<+11>-11
38 | - Etc/GMT-12,<+12>-12
39 | - Etc/GMT-13,<+13>-13
40 | - Etc/GMT-14,<+14>-14
41 | - Etc/GMT0,GMT0
42 | - Etc/GMT+0,GMT0
43 | - Etc/GMT+1,<-01>1
44 | - Etc/GMT+2,<-02>2
45 | - Etc/GMT+3,<-03>3
46 | - Etc/GMT+4,<-04>4
47 | - Etc/GMT+5,<-05>5
48 | - Etc/GMT+6,<-06>6
49 | - Etc/GMT+7,<-07>7
50 | - Etc/GMT+8,<-08>8
51 | - Etc/GMT+9,<-09>9
52 | - Etc/GMT+10,<-10>10
53 | - Etc/GMT+11,<-11>11
54 | - Etc/GMT+12,<-12>12
55 | )~";
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/firmCheckESP8266PMem.h:
--------------------------------------------------------------------------------
1 | const char* VARIABLES_DEF_YAML PROGMEM = R"~(
2 | Wifi settings:
3 | - st_ssid:
4 | label: Name for WLAN
5 | default:
6 | - st_pass:
7 | label: Password for WLAN
8 | default:
9 | - host_name:
10 | label: >-
11 | Host name to use for MDNS and AP {mac} will be replaced with device's mac id
12 | default: configAssist_{mac}
13 |
14 | Application settings:
15 | - app_name:
16 | label: Name your application
17 | default: FirmwareCheck
18 | - firmware_url:
19 | label: Firmware upgrade url with version and info
20 | default: >-
21 | https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/main/examples/ConfigAssist-FirmwareCheck/firmware/ESP8266/lastest.json
22 | - time_zone:
23 | label: Needs to be a valid time zone string
24 | default: EET-2EEST,M3.5.0/3,M10.5.0/4
25 | datalist:
26 | - Etc/GMT,GMT0
27 | - Etc/GMT-0,GMT0
28 | - Etc/GMT-1,<+01>-1
29 | - Etc/GMT-2,<+02>-2
30 | - Etc/GMT-3,<+03>-3
31 | - Etc/GMT-4,<+04>-4
32 | - Etc/GMT-5,<+05>-5
33 | - Etc/GMT-6,<+06>-6
34 | - Etc/GMT-7,<+07>-7
35 | - Etc/GMT-8,<+08>-8
36 | - Etc/GMT-9,<+09>-9
37 | - Etc/GMT-10,<+10>-10
38 | - Etc/GMT-11,<+11>-11
39 | - Etc/GMT-12,<+12>-12
40 | - Etc/GMT-13,<+13>-13
41 | - Etc/GMT-14,<+14>-14
42 | - Etc/GMT0,GMT0
43 | - Etc/GMT+0,GMT0
44 | - Etc/GMT+1,<-01>1
45 | - Etc/GMT+2,<-02>2
46 | - Etc/GMT+3,<-03>3
47 | - Etc/GMT+4,<-04>4
48 | - Etc/GMT+5,<-05>5
49 | - Etc/GMT+6,<-06>6
50 | - Etc/GMT+7,<-07>7
51 | - Etc/GMT+8,<-08>8
52 | - Etc/GMT+9,<-09>9
53 | - Etc/GMT+10,<-10>10
54 | - Etc/GMT+11,<-11>11
55 | - Etc/GMT+12,<-12>12
56 | )~";
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/firmware/ESP32/FirmwareCheck1.0.1.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/f7830b0e43629fceadb76a4bd6e2f7e38cb363a1/examples/ConfigAssist-FirmwareCheck/firmware/ESP32/FirmwareCheck1.0.1.bin
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/firmware/ESP32/lastest.json:
--------------------------------------------------------------------------------
1 | {
2 | "ver" : "1.0.1",
3 | "url" : "https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/main/examples/ConfigAssist-FirmwareCheck/firmware/ESP32/FirmwareCheck1.0.1.bin",
4 | "descr": "A new firmware for ESP32 v1.0.1 with bug fixes and improvements."
5 | }
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/firmware/ESP8266/FirmwareCheck1.0.1.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/f7830b0e43629fceadb76a4bd6e2f7e38cb363a1/examples/ConfigAssist-FirmwareCheck/firmware/ESP8266/FirmwareCheck1.0.1.bin
--------------------------------------------------------------------------------
/examples/ConfigAssist-FirmwareCheck/firmware/ESP8266/lastest.json:
--------------------------------------------------------------------------------
1 | {
2 | "ver" : "1.0.1",
3 | "url" : "https://raw.githubusercontent.com/gemi254/ConfigAssist-ESP32-ESP8266/main/examples/ConfigAssist-FirmwareCheck/firmware/ESP8266/FirmwareCheck1.0.1.bin",
4 | "descr": "A new firmware for ESP8266 v1.0.1 with bug fixes and improvements."
5 | }
--------------------------------------------------------------------------------
/examples/ConfigAssist-LargeTextArea/ConfigAssist-LargeTextArea.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class
2 | #include // Config assist helper class
3 |
4 | #include "appPMem.h"
5 |
6 | #ifndef LED_BUILTIN
7 | #define LED_BUILTIN 22
8 | #endif
9 | #if defined(ESP32)
10 | WebServer server(80);
11 | #else
12 | ESP8266WebServer server(80);
13 | #endif
14 |
15 | #define INI_FILE "/LargeTextArea.ini" // Define SPIFFS storage file
16 |
17 | // Config class
18 | ConfigAssist conf(INI_FILE, VARIABLES_DEF_YAML);
19 |
20 | // Define a ConfigAssist helper class
21 | ConfigAssistHelper confHelper(conf);
22 |
23 | unsigned long pingMillis = millis(); // Ping
24 |
25 | // Handler function for Home page
26 | void handleRoot() {
27 |
28 | String out("
Hello from {name}
");
29 | out += "
Device time: " + conf.getLocalTime() +"
";
30 | out += "Edit config";
31 |
32 | #if defined(ESP32)
33 | out.replace("{name}", "ESP32");
34 | #else
35 | out.replace("{name}", "ESP8266");
36 | #endif
37 | // Setup time sync script in home page
38 | // When page opened by browser if esp time
39 | // is not set will be synchronized wih remote host time
40 | #if (CA_USE_TIMESYNC)
41 | out += "";
42 | #endif
43 | server.send(200, "text/html", out);
44 | }
45 |
46 | // Handler for page not found
47 | void handleNotFound() {
48 | String message = "File Not Found\n\n";
49 | message += "URI: ";
50 | message += server.uri();
51 | message += "\nMethod: ";
52 | message += (server.method() == HTTP_GET) ? "GET" : "POST";
53 | message += "\nArguments: ";
54 | message += server.args();
55 | message += "\n";
56 | for (uint8_t i = 0; i < server.args(); i++) {
57 | message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
58 | }
59 | server.send(404, "text/plain", message);
60 | }
61 |
62 | // Setup function
63 | void setup(void) {
64 |
65 | // Setup internal led variable if not set
66 | if (conf("led_buildin") == "") conf["led_buildin"] = LED_BUILTIN;
67 |
68 | Serial.begin(115200);
69 | Serial.print("\n\n\n\n");
70 | Serial.flush();
71 |
72 | LOG_I("Starting.. \n");
73 |
74 | //conf.deleteConfig(); // Uncomment to remove old ini file and re-built it fron dictionary
75 |
76 | //Active seperator open/close, All others closed
77 | conf.setDisplayType(ConfigAssistDisplayType::AccordionToggleClosed);
78 |
79 | // Register handlers for web server
80 | server.on("/", handleRoot);
81 | server.on("/d", []() { // Append dump handler
82 | conf.dump(&server);
83 | });
84 | server.onNotFound(handleNotFound); // Append not found handler
85 |
86 | // Connect to any available network
87 | bool bConn = confHelper.connectToNetwork(15000, conf("led_buildin").toInt());
88 |
89 | // Append config assist handlers to web server, setup ap on no connection
90 | conf.setup(server, !bConn);
91 | if(!bConn) LOG_E("Connect failed.\n");
92 | else confHelper.startMDNS();
93 |
94 | // Start web server
95 | server.begin();
96 | LOG_I("HTTP server started\n");
97 | }
98 |
99 | // App main loop
100 | void loop(void) {
101 | server.handleClient();
102 | confHelper.loop();
103 | }
104 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-LargeTextArea/appPMem.h:
--------------------------------------------------------------------------------
1 | const char* VARIABLES_DEF_YAML PROGMEM = R"~(
2 | Wifi settings:
3 | - st_ssid:
4 | label: Name for WLAN
5 | default:
6 | - st_pass:
7 | label: Password for WLAN
8 | default:
9 | - host_name:
10 | label: >-
11 | Host name to use for MDNS and AP {mac} will be replaced with device's mac id
12 | default: configAssist_{mac}
13 |
14 | Server Security:
15 | - login_usr: admin
16 | label: User name for login authentication
17 | default: admin
18 | - login_pass:
19 | label: Password for login authentication
20 | default: admin
21 |
22 | - server_cert:
23 | label: >-
24 | Encryption certificate.
25 | These can generated with the bash script available in the ESP8266 Arduino repository
26 | file: "/cert.ini"
27 | attribs: style="width: 254px; height:190px;"
28 | default: >-
29 | -----BEGIN CERTIFICATE-----
30 | MIIDSzCCAjMCCQD2ahcfZAwXxDANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMC
31 | VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU9yYW5nZSBDb3VudHkx
32 | EDAOBgNVBAoMB1ByaXZhZG8xGjAYBgNVBAMMEXNlcnZlci56bGFiZWwuY29tMR8w
33 | HQYJKoZIhvcNAQkBFhBlYXJsZUB6bGFiZWwuY29tMB4XDTE4MDMwNjA1NDg0NFoX
34 | DTE5MDMwNjA1NDg0NFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh
35 | dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZI
36 | hvcNAQEBBQADggEPADCCAQoCggEBAPVKBwbZ+KDSl40YCDkP6y8Sv4iNGvEOZg8Y
37 | X7sGvf/xZH7UiCBWPFIRpNmDSaZ3yjsmFqm6sLiYSGSdrBCFqdt9NTp2r7hga6Sj
38 | oASSZY4B9pf+GblDy5m10KDx90BFKXdPMCLT+o76Nx9PpCvw13A848wHNG3bpBgI
39 | t+w/vJCX3bkRn8yEYAU6GdMbYe7v446hX3kY5UmgeJFr9xz1kq6AzYrMt/UHhNzO
40 | S+QckJaY0OGWvmTNspY3xCbbFtIDkCdBS8CZAw+itnofvnWWKQEXlt6otPh5njwy
41 | +O1t/Q+Z7OMDYQaH02IQx3188/kW3FzOY32knER1uzjmRO+jhA8CAwEAATANBgkq
42 | hkiG9w0BAQsFAAOCAQEAnDrROGRETB0woIcI1+acY1yRq4yAcH2/hdq2MoM+DCyM
43 | E8CJaOznGR9ND0ImWpTZqomHOUkOBpvu7u315blQZcLbL1LfHJGRTCHVhvVrcyEb
44 | fWTnRtAQdlirUm/obwXIitoz64VSbIVzcqqfg9C6ZREB9JbEX98/9Wp2gVY+31oC
45 | JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m
46 | +TGimzSdeWDvGBRWZHXczC2zD4aoE5vrl+GD2i++c6yjL/otHfYyUpzUfbI2hMAA
47 | 5tAF1D5vAAwA8nfPysumlLsIjohJZo4lgnhB++AlOg==
48 | -----END CERTIFICATE-----
49 | - server_key:
50 | label: >-
51 | Encryption key.
52 | These can generated with the bash script available in the ESP8266 Arduino repository
53 | file: "/key.ini"
54 | attribs: style="width: 254px; height:192px;"
55 | default: >-
56 | -----BEGIN RSA PRIVATE KEY-----
57 | MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI
58 | IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z
59 | uUPLmbXQoPH3QEUpd08wItP6jvo3H0+kK/DXcDzjzAc0bdukGAi37D+8kJfduRGf
60 | zIRgBToZ0xth7u/jjqFfeRjlSaB4kWv3HPWSroDNisy39QeE3M5L5ByQlpjQ4Za+
61 | ZM2yljfEJtsW0gOQJ0FLwJkDD6K2eh++dZYpAReW3qi0+HmePDL47W39D5ns4wNh
62 | BofTYhDHfXzz+RbcXM5jfaScRHW7OOZE76OEDwIDAQABAoIBAQDKov5NFbNFQNR8
63 | djcM1O7Is6dRaqiwLeH4ZH1pZ3d9QnFwKanPdQ5eCj9yhfhJMrr5xEyCqT0nMn7T
64 | yEIGYDXjontfsf8WxWkH2TjvrfWBrHOIOx4LJEvFzyLsYxiMmtZXvy6YByD+Dw2M
65 | q2GH/24rRdI2klkozIOyazluTXU8yOsSGxHr/aOa9/sZISgLmaGOOuKI/3Zqjdhr
66 | eHeSqoQFt3xXa8jw01YubQUDw/4cv9rk2ytTdAoQUimiKtgtjsggpP1LTq4xcuqN
67 | d4jWhTcnorWpbD2cVLxrEbnSR3VuBCJEZv5axg5ZPxLEnlcId8vMtvTRb5nzzszn
68 | geYUWDPhAoGBAPyKVNqqwQl44oIeiuRM2FYenMt4voVaz3ExJX2JysrG0jtCPv+Y
69 | 84R6Cv3nfITz3EZDWp5sW3OwoGr77lF7Tv9tD6BptEmgBeuca3SHIdhG2MR+tLyx
70 | /tkIAarxQcTGsZaSqra3gXOJCMz9h2P5dxpdU+0yeMmOEnAqgQ8qtNBfAoGBAPim
71 | RAtnrd0WSlCgqVGYFCvDh1kD5QTNbZc+1PcBHbVV45EmJ2fLXnlDeplIZJdYxmzu
72 | DMOxZBYgfeLY9exje00eZJNSj/csjJQqiRftrbvYY7m5njX1kM5K8x4HlynQTDkg
73 | rtKO0YZJxxmjRTbFGMegh1SLlFLRIMtehNhOgipRAoGBAPnEEpJGCS9GGLfaX0HW
74 | YqwiEK8Il12q57mqgsq7ag7NPwWOymHesxHV5mMh/Dw+NyBi4xAGWRh9mtrUmeqK
75 | iyICik773Gxo0RIqnPgd4jJWN3N3YWeynzulOIkJnSNx5BforOCTc3uCD2s2YB5X
76 | jx1LKoNQxLeLRN8cmpIWicf/AoGBANjRSsZTKwV9WWIDJoHyxav/vPb+8WYFp8lZ
77 | zaRxQbGM6nn4NiZI7OF62N3uhWB/1c7IqTK/bVHqFTuJCrCNcsgld3gLZ2QWYaMV
78 | kCPgaj1BjHw4AmB0+EcajfKilcqtSroJ6MfMJ6IclVOizkjbByeTsE4lxDmPCDSt
79 | /9MKanBxAoGAY9xo741Pn9WUxDyRplww606ccdNf/ksHWNc/Y2B5SPwxxSnIq8nO
80 | j01SmsCUYVFAgZVOTiiycakjYLzxlc6p8BxSVqy6LlJqn95N8OXoQ+bkwUux/ekg
81 | gz5JWYhbD6c38khSzJb0pNXCo3EuYAVa36kDM96k1BtWuhRS10Q1VXk=
82 | -----END RSA PRIVATE KEY-----
83 | Application settings:
84 | - app_name:
85 | label: Name your application
86 | default: LargeTextArea
87 | - led_buildin:
88 | label: Enter the pin that the build in led is connected.
89 | Leave blank for auto.
90 | attribs: "min='2' max='23' step='1'"
91 | default:
92 | )~";
93 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-LogExternal/ConfigAssist-LogExternal.ino:
--------------------------------------------------------------------------------
1 | #define LOGGER_LOG_MODE 3 // Set default logging mode using external function
2 | #define LOGGER_LOG_FILENAME "/logE"
3 | #define LOGGER_LOG_LEVEL 5 // Errors & Warnings & Info & Debug & Verbose
4 | void _log_printf(const char *format, ...); // Provide custom print log function
5 |
6 | #include // Config assist class
7 |
8 | bool logToFile = true;
9 | static File logFile;
10 |
11 | #define MAX_LOG_FMT 128
12 | static char fmtBuf[MAX_LOG_FMT];
13 | static char outBuf[512];
14 | static va_list arglist;
15 |
16 | // Custom log print function
17 | void _log_printf(const char *format, ...){
18 | strncpy(fmtBuf, format, MAX_LOG_FMT);
19 | fmtBuf[MAX_LOG_FMT - 1] = 0;
20 | va_start(arglist, format);
21 | vsnprintf(outBuf, MAX_LOG_FMT, fmtBuf, arglist);
22 | va_end(arglist);
23 | Serial.print(outBuf);
24 | if (logToFile){
25 | if(!logFile) logFile = STORAGE.open(LOGGER_LOG_FILENAME, "a+");
26 | if(!logFile){
27 | Serial.printf("Failed to open log file: %s\n", LOGGER_LOG_FILENAME);
28 | logToFile = false;
29 | return;
30 | }
31 | logFile.print(outBuf);
32 | logFile.flush();
33 | }
34 | }
35 |
36 | // Print the log generated to serial port
37 | void serialPrintLog(){
38 | Serial.printf("Display log: %s\n", LOGGER_LOG_FILENAME);
39 | File f = STORAGE.open(LOGGER_LOG_FILENAME, "r");
40 | // Read from the file until there's nothing else in it:
41 | while (f.available())
42 | {
43 | Serial.write(f.read());
44 | }
45 | // close the file:
46 | f.close();
47 | Serial.print("\nDisplay log..Done\n");
48 | }
49 |
50 | // Setup function
51 | void setup() {
52 | Serial.begin(115200);
53 | Serial.print("\n\n\n\n");
54 | Serial.flush();
55 | Serial.print("Starting..\n");
56 |
57 | #if defined(ESP32)
58 | if(!STORAGE.begin(true)) Serial.println("ESP32 storage init failed!");
59 | #else
60 | if(!STORAGE.begin()) Serial.println("ESP8266 storage init failed!");
61 | #endif
62 |
63 | // Display the log file
64 | serialPrintLog();
65 |
66 | LOG_I("* * * * Starting * * * * * \n");
67 |
68 | LOG_E("F:This is an ERROR message \n");
69 | LOG_W("F:This is a WARNING message \n");
70 | LOG_I("F:This is an INFO message \n");
71 | LOG_D("F:This is a DEBUG message \n");
72 | LOG_V("F:This is a VERBOSE message \n");
73 |
74 | // Create a config class with an ini filename and no dictionary
75 | ConfigAssist info("/info.ini");
76 |
77 | if(false){ // Set to true to reset
78 | info.deleteConfig(); // Remove ini file and re-built
79 | info.clear(); // Clear loaded keys
80 | STORAGE.remove(LOGGER_LOG_FILENAME);
81 | }
82 | if(!info.valid()){ //Add boot counter
83 | info["bootCnt"] = 1;
84 | }else{ // Ini is valid, increase counter and display the value
85 | info["bootCnt"] = info("bootCnt").toInt() + 1;
86 | LOG_I("Info file: bootCnt: %lu\n", info("bootCnt").toInt());
87 | }
88 | // ave keys & values into ini file
89 | info.saveConfigFile();
90 |
91 | // On the fly Stop loggin to file
92 | logToFile = false;
93 | logFile.close();
94 |
95 | LOG_E("S:This is an ERROR message \n");
96 | LOG_W("S:This is a WARNING message \n");
97 | LOG_I("S:This is an INFO message \n");
98 | LOG_D("S:This is a DEBUG message \n");
99 | LOG_V("S:This is a VERBOSE message \n");
100 |
101 | LOG_D("End of setup()..\n");
102 |
103 | }
104 |
105 | void loop() {
106 | // put your main code here, to run repeatedly:
107 |
108 | }
109 |
110 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-LogToFile/ConfigAssist-LogToFile.ino:
--------------------------------------------------------------------------------
1 | #define LOGGER_LOG_MODE 2 // Log to file
2 | #define LOGGER_LOG_LEVEL 5 // Errors & Warnings & Info & Debug & Verbose
3 | #define LOGGER_LOG_FILENAME "/log1"
4 |
5 | #include // Config assist class
6 |
7 | // Print the log generated to serial port
8 | void serialPrintLog(){
9 | Serial.printf("Display log: %s\n", LOGGER_LOG_FILENAME);
10 | File f = STORAGE.open(LOGGER_LOG_FILENAME, "r");
11 | // read from the file until there's nothing else in it:
12 | while (f.available())
13 | {
14 | Serial.write(f.read());
15 | }
16 | // close the file:
17 | f.close();
18 | Serial.print("\nDisplay log..Done\n");
19 | }
20 |
21 | // Setup function
22 | void setup() {
23 | Serial.begin(115200);
24 | Serial.print("\n\n\n\n");
25 | Serial.flush();
26 | Serial.print("Starting..\n");
27 |
28 | #if defined(ESP32)
29 | if(!STORAGE.begin(true)) Serial.println("ESP32 storage init failed!");
30 | #else
31 | if(!STORAGE.begin()) Serial.println("ESP8266 storage init failed!");
32 | #endif
33 |
34 | //STORAGE.remove(LOGGER_LOG_FILENAME); //Uncomment to reset the log file
35 |
36 | //Display the log file
37 | serialPrintLog();
38 |
39 | LOG_I("* * * * Starting * * * * * \n");
40 |
41 | LOG_E("This is an ERROR message \n");
42 | LOG_W("This is a WARNING message \n");
43 | LOG_I("This is an INFO message \n");
44 | LOG_D("This is a DEBUG message \n");
45 | LOG_V("This is a VERBOSE message \n");
46 |
47 | // Create a config class with an ini filename and disabled dictionary
48 | ConfigAssist info("/info.ini");
49 |
50 | //info.deleteConfig(); //Uncomment to remove ini file and re-built
51 |
52 | if(!info.valid()){ //Add boot counter
53 | info["bootCnt"] = 1;
54 | }else{ //Ini is valid, increase counter and display the value
55 | info["bootCnt"] = info("bootCnt").toInt() + 1;
56 | LOG_I("Info file: bootCnt: %lu\n", info("bootCnt").toInt());
57 | }
58 | //Save keys & values into ini file
59 | info.saveConfigFile();
60 | LOG_D("End of setup()..\n");
61 | LOGGER_CLOSE_LOG()
62 | }
63 |
64 | void loop() {
65 | // put your main code here, to run repeatedly:
66 |
67 | }
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-Minimal/ConfigAssist-Minimal.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class
2 | #include // Config assist helper class
3 | #if defined(ESP32)
4 | WebServer server(80);
5 | #else
6 | ESP8266WebServer server(80);
7 | #endif
8 | // Create a config class with an ini filename for storage
9 | // Default wifi connect credentials yaml
10 | ConfigAssist conf("/minimal.ini", true);
11 |
12 | void setup() {
13 | // put your setup code here, to run once:
14 |
15 | Serial.begin(115200);
16 | Serial.print("\n\n\n\n");
17 | Serial.flush();
18 |
19 | LOG_I("Starting..\n");
20 |
21 | //conf.deleteConfig(); // Uncomment to remove ini file and re-built
22 |
23 | // Define a ConfigAssist helper
24 | ConfigAssistHelper confHelper(conf);
25 |
26 | // Connect to any available network
27 | bool bConn = confHelper.connectToNetwork(15000);
28 | if(!bConn) LOG_E("Connect failed.\n");
29 |
30 | // Start AP to fix wifi credentials
31 | conf.setup(server, !bConn);
32 |
33 | server.on("/", []() { // Append dump handler
34 | conf.init();
35 | conf.dump(&server);
36 | });
37 |
38 | // Start web server
39 | server.begin();
40 | conf.dump();
41 | }
42 |
43 | void loop() {
44 | // put your main code here, to run repeatedly:
45 | server.handleClient();
46 | }
47 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-NtpTimeSync/ConfigAssist-NtpTimeSync.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class
2 | #include // Config assist helper class
3 |
4 | #include "appPMem.h"
5 |
6 | #ifndef LED_BUILTIN
7 | #define LED_BUILTIN 22
8 | #endif
9 | #if defined(ESP32)
10 | WebServer server(80);
11 | #else
12 | ESP8266WebServer server(80);
13 | #endif
14 |
15 | #define INI_FILE "/NtpTimeSync.ini" // Define SPIFFS storage file
16 |
17 | // Config class
18 | ConfigAssist conf(INI_FILE, VARIABLES_DEF_YAML);
19 |
20 | // Define a ConfigAssist helper class
21 | ConfigAssistHelper confHelper(conf);
22 |
23 | // Setup internal led variable if not set
24 | String s = (conf("led_buildin") == "") ? conf["led_buildin"] = LED_BUILTIN : "";
25 |
26 | time_t tnow;
27 | unsigned long pingMillis = millis(); // Ping
28 |
29 | // Handler function for Home page
30 | void handleRoot() {
31 |
32 | String out("
Hello from {name}
");
33 | out += "
Device time: " + conf.getLocalTime() +"
";
34 | out += "Edit config";
35 |
36 | #if defined(ESP32)
37 | out.replace("{name}", "ESP32");
38 | #else
39 | out.replace("{name}", "ESP8266!");
40 | #endif
41 |
42 | #if (CA_USE_TIMESYNC)
43 | // Send a web browser sync java script to client
44 | out += "";
45 | #endif
46 | server.send(200, "text/html", out);
47 | }
48 |
49 | // Handler for page not found
50 | void handleNotFound() {
51 | String message = "File Not Found\n\n";
52 | message += "URI: ";
53 | message += server.uri();
54 | message += "\nMethod: ";
55 | message += (server.method() == HTTP_GET) ? "GET" : "POST";
56 | message += "\nArguments: ";
57 | message += server.args();
58 | message += "\n";
59 | for (uint8_t i = 0; i < server.args(); i++) {
60 | message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
61 | }
62 | server.send(404, "text/plain", message);
63 | }
64 |
65 |
66 | void onConnectionResult(ConfigAssistHelper::WiFiResult result, const String& msg){
67 |
68 | switch (result) {
69 | case ConfigAssistHelper::WiFiResult::SUCCESS:
70 | LOG_D("Connected to Wi-Fi! IP: %s\n", msg.c_str());
71 | confHelper.startMDNS();
72 | conf.setupConfigPortalHandlers(server);
73 | // Start web server
74 | server.begin();
75 | LOG_I("HTTP server started\n");
76 | LOG_I("Device started. Visit http://%s\n", WiFi.localIP().toString().c_str());
77 |
78 | // Setup time synchronization, Wait max 10 sec
79 | LOG_I("Start time sync..\n");
80 | confHelper.syncTime(10000);
81 | pingMillis = millis();
82 | tnow = time(nullptr);
83 | break;
84 |
85 | case ConfigAssistHelper::WiFiResult::INVALID_CREDENTIALS:
86 | LOG_D("Invalid credentials: %s\n", msg.c_str());
87 | // Append config assist handlers to web server, setup ap on no connection
88 | conf.setup(server, true);
89 | break;
90 |
91 | case ConfigAssistHelper::WiFiResult::CONNECTION_TIMEOUT:
92 | LOG_D("Connection fail: %s\n", msg.c_str());
93 | conf.setup(server, true);
94 | break;
95 |
96 | case ConfigAssistHelper::WiFiResult::DISCONNECTION_ERROR:
97 | LOG_D("Disconnect: %s\n", msg.c_str());
98 | WiFi.setAutoReconnect(true);
99 | confHelper.setReconnect(true);
100 | break;
101 |
102 | default:
103 | LOG_D("Unknown result: %s\n", msg.c_str());
104 | break;
105 | }
106 | }
107 |
108 | // Setup function
109 | void setup(void) {
110 |
111 | Serial.begin(115200);
112 | Serial.print("\n\n\n\n");
113 | Serial.flush();
114 |
115 | LOG_I("Starting.. \n");
116 | if(false) conf.deleteConfig(); //Set to true to remove old ini file and re-built it fron dictionary
117 |
118 | //Active seperator open/close, All others closed
119 | conf.setDisplayType(ConfigAssistDisplayType::AccordionToggleClosed);
120 |
121 | // Register handlers for web server
122 | server.on("/", handleRoot);
123 | server.on("/d", []() { // Append dump handler
124 | conf.dump(&server);
125 | });
126 | server.onNotFound(handleNotFound); // Append not found handler
127 | confHelper.setWiFiResultCallback(onConnectionResult);
128 | // Connect to any available network
129 | confHelper.connectToNetworkAsync(15000, conf("led_buildin").toInt());
130 | }
131 |
132 | int syncType = 0;
133 |
134 |
135 | // App main loop
136 | void loop(void) {
137 | server.handleClient();
138 | // Update led, print dots when connecting, check connection on connected
139 | confHelper.loop();
140 |
141 | if(!WiFi.isConnected()) return;
142 | // Display info
143 | if (millis() - pingMillis >= 20000){
144 | tnow = time(nullptr);
145 | LOG_I("Time in sync: %i clock: %s", confHelper.isTimeSync(), ctime(&tnow));
146 | syncType++;
147 | pingMillis = millis();
148 | }else{
149 | return;
150 | }
151 |
152 | if(syncType == 1){
153 | // Force time synchronization,
154 | // syncTime will not wait if already time is set
155 | // and time will be automatically sync in background.
156 | LOG_I("* * * Starting soft resync time...\n");
157 | confHelper.syncTime(conf("sync_timeout").toInt() * 1000L, false);
158 | tnow = time(nullptr);
159 | LOG_I("Soft resync time: %i clock: %s", confHelper.isTimeSync(), ctime(&tnow));
160 |
161 | }else if(syncType == 2){
162 | // Force time synchronization,
163 | // Clock will be reseted and wait for max 20 sec to sync
164 | // If fail clock will be restored
165 | LOG_I("* * * Starting hard resync time...\n");
166 | confHelper.syncTime(conf("sync_timeout").toInt() * 1000L, true);
167 | tnow = time(nullptr);
168 | LOG_I("Hard resynced time: %i clock: %s", confHelper.isTimeSync(), ctime(&tnow));
169 | }else if(syncType == 3){
170 | // Force time synchronization and don't wait for Synchronization
171 | LOG_I("* * * Starting ASYNC hard resync time...\n");
172 | confHelper.syncTimeAsync(conf("sync_timeout").toInt() * 1000L, true);
173 | tnow = time(nullptr);
174 | LOG_N("ASYNC Hard resynced time: %i clock: %s", confHelper.isTimeSync(), ctime(&tnow));
175 | }
176 | if(syncType > 3) syncType = 0;
177 | // Allow the cpu to switch to other tasks
178 | delay(2);
179 | }
180 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-NtpTimeSync/appPMem.h:
--------------------------------------------------------------------------------
1 | const char* VARIABLES_DEF_YAML PROGMEM = R"~(
2 | Wifi settings:
3 | - st_ssid:
4 | label: Name for WLAN
5 | - st_pass:
6 | label: Password for WLAN
7 | - host_name:
8 | label: >-
9 | Host name to use for MDNS and AP {mac} will be replaced with device's mac id
10 | default: configAssist_{mac}
11 |
12 | Application settings:
13 | - app_name:
14 | label: Name your application
15 | default: NtpTimeSync
16 | - led_buildin:
17 | label: Enter the pin that the build in led is connected.
18 | Leave blank for auto.
19 | attribs: "min='2' max='23' step='1'"
20 |
21 | Time settings:
22 | - time_zone:
23 | label: Needs to be a valid time zone string
24 | default: EET-2EEST,M3.5.0/3,M10.5.0/4
25 | datalist:
26 | - Etc/GMT,GMT0
27 | - Etc/GMT-0,GMT0
28 | - Etc/GMT-1,<+01>-1
29 | - Etc/GMT-2,<+02>-2
30 | - Etc/GMT-3,<+03>-3
31 | - Etc/GMT-4,<+04>-4
32 | - Etc/GMT-5,<+05>-5
33 | - Etc/GMT-6,<+06>-6
34 | - Etc/GMT-7,<+07>-7
35 | - Etc/GMT-8,<+08>-8
36 | - Etc/GMT-9,<+09>-9
37 | - Etc/GMT-10,<+10>-10
38 | - Etc/GMT-11,<+11>-11
39 | - Etc/GMT-12,<+12>-12
40 | - Etc/GMT-13,<+13>-13
41 | - Etc/GMT-14,<+14>-14
42 | - Etc/GMT0,GMT0
43 | - Etc/GMT+0,GMT0
44 | - Etc/GMT+1,<-01>1
45 | - Etc/GMT+2,<-02>2
46 | - Etc/GMT+3,<-03>3
47 | - Etc/GMT+4,<-04>4
48 | - Etc/GMT+5,<-05>5
49 | - Etc/GMT+6,<-06>6
50 | - Etc/GMT+7,<-07>7
51 | - Etc/GMT+8,<-08>8
52 | - Etc/GMT+9,<-09>9
53 | - Etc/GMT+10,<-10>10
54 | - Etc/GMT+11,<-11>11
55 | - Etc/GMT+12,<-12>12
56 |
57 | - ntp_server1:
58 | label: Time server to sync time1
59 | default: "europe.pool.ntp.org"
60 | - ntp_server2:
61 | label: Time server to sync time2
62 | default: "time.windows.com"
63 | - ntp_server3:
64 | label: Time server to sync time3
65 | default: "pool.ntp.org"
66 |
67 | - sync_timeout:
68 | label: Timeout for time sync (sec)
69 | default: 15
70 | )~";
71 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-Simple/ConfigAssist-Simple.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class
2 | bool reset = false;
3 |
4 | void setup() {
5 | // put your setup code here, to run once:
6 |
7 | Serial.begin(115200);
8 | Serial.print("\n\n\n\n");
9 | Serial.flush();
10 |
11 | LOG_I("Starting..\n");
12 |
13 | // Create a config class with an ini filename for storage
14 | // and disabled yaml dictionary (NULL)
15 | // If ini file exists load it
16 | ConfigAssist info("/info.ini");
17 |
18 | if(reset){
19 | info.deleteConfig(); // Remove ini file and re-built
20 | info.clear(); // Clear loaded keys
21 | }
22 | // Ini file not exists
23 | if(!info.confExists()) {
24 | // Add a key even if not exists.
25 | // It will be not editable, but it will be saved to an ini file
26 | LOG_I("Config file not exists\n");
27 | info["string"] = "This is a string";
28 | info["numString"] = "12345";
29 | info["integer"] = 1;
30 | info["float"] = 1.0;
31 |
32 | }else{ // Ini file is valid, display the values
33 | LOG_I("Config file already exists\n");
34 | info["integer"] = info("integer").toInt() + 1;
35 | info["float"] = info("float").toFloat() + .5;
36 | }
37 | // Save keys & values into an ini file
38 | info.saveConfigFile();
39 | info.dump();
40 | }
41 |
42 | void loop() {
43 | // put your main code here, to run repeatedly:
44 | }
45 |
--------------------------------------------------------------------------------
/examples/ConfigAssist-Test-Wifi/ConfigAssist-Test-Wifi.ino:
--------------------------------------------------------------------------------
1 | #include // Config assist class
2 | #include // Config assist helper class
3 |
4 | #if defined(ESP32)
5 | WebServer server(80);
6 | #else
7 | ESP8266WebServer server(80);
8 | #endif
9 |
10 | #define INI_FILE "/TestWifi.ini" // Define SPIFFS storage file
11 |
12 | #ifndef LED_BUILTIN
13 | #define LED_BUILTIN 22
14 | #endif
15 | const char* VARIABLES_DEF_YAML PROGMEM = R"~(
16 | Wifi connection settings:
17 | - st_ssid1:
18 | label: Name for WLAN 1
19 | - st_pass1:
20 | label: Password for WLAN 1
21 | - st_ip1:
22 | label: Static ip setup (ip mask gateway) (192.168.1.100 255.255.255.0 192.168.1.1)
23 |
24 | - st_ssid2:
25 | label: Name for WLAN 2
26 | - st_pass2:
27 | label: Password for WLAN 2
28 | - st_ip2:
29 | label: Static ip setup (ip mask gateway) (192.168.1.100 255.255.255.0 192.168.1.1)
30 |
31 | - st_ssid3:
32 | label: Name for WLAN 3
33 | - st_pass3:
34 | label: Password for WLAN
35 | - st_ip3:
36 | label: Static ip setup (ip mask gateway) (192.168.1.100 255.255.255.0 192.168.1.1)
37 |
38 | - connect_timeout:
39 | label: Seconds to wait until ST connection
40 | default: 10
41 | - conn_failover:
42 | label: Connect to next wifi on connection fail.
43 | checked: true
44 |
45 | Wifi Access Point settings:
46 | - ap_ssid:
47 | label: Access point ssid. (Leave blank for defaule)
48 | - ap_pass:
49 | label: Password for Access point, leave blank for none.
50 | - ap_ip:
51 | label: Static ip setup (ip mask gateway) (192.168.4.1 255.255.255.0 192.168.4.1)
52 |
53 | Application settings:
54 | - host_name:
55 | label: >-
56 | Host name to use for MDNS and AP {mac} will be replaced with device's mac id
57 | default: configAssist_{mac}
58 | - app_name:
59 | label: Name your application
60 | default: TestWifi
61 | - led_buildin:
62 | label: Enter the pin that the build in led is connected.
63 | Leave blank for auto.
64 | attribs: "min='2' max='23' step='1'"
65 | - debug:
66 | label: Debug application
67 | checked: false
68 | )~";
69 |
70 | ConfigAssist conf(INI_FILE, VARIABLES_DEF_YAML);
71 | // Define a ConfigAssist helper class to manage wifi connections
72 | ConfigAssistHelper confHelper(conf);
73 |
74 | String hostName;
75 | unsigned long pingMillis = millis();
76 |
77 | // Print memory info
78 | void debugMemory(const char* caller) {
79 | #if defined(ESP32)
80 | LOG_D("%s > Free: heap %u, block: %u, pSRAM %u\n", caller, ESP.getFreeHeap(), heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), ESP.getFreePsram());
81 | #else
82 | LOG_D("%s > Free: heap %u\n", caller, ESP.getFreeHeap());
83 | LOG_D("%s > WiFi: %i, state: %i\n", caller, WiFi.isConnected(), (int)confHelper.getLedState() );
84 | #endif
85 | }
86 |
87 | // Web server root handler
88 | void handleRoot() {
89 | String out("