/* Elements.ino, Example for the AutoConnect library. Copyright (c) 2019, Hieromon Ikasamo https://github.com/Hieromon/AutoConnect This software is released under the MIT License. https://opensource.org/licenses/MIT This example demonstrates the typical behavior of AutoConnectElement. It also represents a basic structural frame for saving and reusing values ​​entered in a custom web page into flash. */ #if defined(ARDUINO_ARCH_ESP8266) #include #include using WebServerClass = ESP8266WebServer; #elif defined(ARDUINO_ARCH_ESP32) #include #include #include using WebServerClass = WebServer; #endif #include /* AC_USE_SPIFFS indicates SPIFFS or LittleFS as available file systems that will become the AUTOCONNECT_USE_SPIFFS identifier and is exported as showng the valid file system. After including AutoConnect.h, the Sketch can determine whether to use FS.h or LittleFS.h by AUTOCONNECT_USE_SPIFFS definition. */ #ifdef AUTOCONNECT_USE_SPIFFS #include FS& FlashFS = SPIFFS; #else #include FS& FlashFS = LittleFS; #endif #define PARAM_FILE "/elements.json" #define USERNAME "username_you_wish" // For HTTP authentication #define PASSWORD "password_you_wish" // For HTTP authentication static const char PAGE_ELEMENTS[] PROGMEM = R"( { "uri": "/elements", "title": "Elements", "menu": true, "element": [ { "name": "text", "type": "ACText", "value": "AutoConnect element behaviors collection", "style": "font-family:Arial;font-size:18px;font-weight:400;color:#191970" }, { "name": "check", "type": "ACCheckbox", "value": "check", "label": "Check", "labelposition": "infront", "checked": true }, { "name": "input", "type": "ACInput", "label": "Text input", "placeholder": "This area accepts hostname patterns", "pattern": "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$" }, { "name": "radio", "type": "ACRadio", "value": [ "Button-1", "Button-2", "Button-3" ], "label": "Radio buttons", "arrange": "vertical", "checked": 1 }, { "name": "select", "type": "ACSelect", "option": [ "Option-1", "Option-2", "Option-3" ], "label": "Select", "selected": 2 }, { "name": "load", "type": "ACSubmit", "value": "Load", "uri": "/elements" }, { "name": "save", "type": "ACSubmit", "value": "Save", "uri": "/save" }, { "name": "adjust_width", "type": "ACElement", "value": "" } ] } )"; static const char PAGE_SAVE[] PROGMEM = R"( { "uri": "/save", "title": "Elements", "menu": false, "element": [ { "name": "caption", "type": "ACText", "format": "Elements have been saved to %s", "style": "font-family:Arial;font-size:18px;font-weight:400;color:#191970" }, { "name": "validated", "type": "ACText", "style": "color:red" }, { "name": "echo", "type": "ACText", "style": "font-family:monospace;font-size:small;white-space:pre;" }, { "name": "ok", "type": "ACSubmit", "value": "OK", "uri": "/elements" } ] } )"; WebServerClass server; AutoConnect portal(server); AutoConnectConfig config; AutoConnectAux elementsAux; AutoConnectAux saveAux; void setup() { delay(1000); Serial.begin(115200); Serial.println(); // Responder of root page handled directly from WebServer class. server.on("/", []() { String content = "Place the root page with the sketch application. "; content += AUTOCONNECT_LINK(COG_24); server.send(200, "text/html", content); }); // Load a custom web page described in JSON as PAGE_ELEMENT and // register a handler. This handler will be invoked from // AutoConnectSubmit named the Load defined on the same page. elementsAux.load(FPSTR(PAGE_ELEMENTS)); elementsAux.on([] (AutoConnectAux& aux, PageArgument& arg) { if (portal.where() == "/elements") { // Use the AutoConnect::where function to identify the referer. // Since this handler only supports AutoConnectSubmit called the // Load, it uses the uri of the custom web page placed to // determine whether the Load was called me or not. FlashFS.begin(); File param = FlashFS.open(PARAM_FILE, "r"); if (param) { aux.loadElement(param, { "text", "check", "input", "radio", "select" } ); param.close(); } FlashFS.end(); } return String(); }); saveAux.load(FPSTR(PAGE_SAVE)); saveAux.on([] (AutoConnectAux& aux, PageArgument& arg) { // You can validate input values ​​before saving with // AutoConnectInput::isValid function. // Verification is using performed regular expression set in the // pattern attribute in advance. AutoConnectInput& input = elementsAux["input"].as(); aux["validated"].value = input.isValid() ? String() : String("Input data pattern missmatched."); // The following line sets only the value, but it is HTMLified as // formatted text using the format attribute. aux["caption"].value = PARAM_FILE; #if defined(ARDUINO_ARCH_ESP8266) FlashFS.begin(); #elif defined(ARDUINO_ARCH_ESP32) FlashFS.begin(true); #endif File param = FlashFS.open(PARAM_FILE, "w"); if (param) { // Save as a loadable set for parameters. elementsAux.saveElement(param, { "text", "check", "input", "radio", "select" }); param.close(); // Read the saved elements again to display. param = FlashFS.open(PARAM_FILE, "r"); aux["echo"].value = param.readString(); param.close(); } else { aux["echo"].value = "Filesystem failed to open."; } FlashFS.end(); return String(); }); portal.join({ elementsAux, saveAux }); config.auth = AC_AUTH_DIGEST; config.authScope = AC_AUTHSCOPE_AUX; config.username = USERNAME; config.password = PASSWORD; config.ticker = true; portal.config(config); portal.begin(); } void loop() { portal.handleClient(); }