Elements.ino 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. Elements.ino, Example for the AutoConnect library.
  3. Copyright (c) 2020, Hieromon Ikasamo
  4. https://github.com/Hieromon/AutoConnect
  5. This software is released under the MIT License.
  6. https://opensource.org/licenses/MIT
  7. This example demonstrates the typical behavior of AutoConnectElement.
  8. It also represents a basic structural frame for saving and reusing
  9. values ​​entered in a custom web page into flash.
  10. */
  11. #if defined(ARDUINO_ARCH_ESP8266)
  12. #include <ESP8266WiFi.h>
  13. #include <ESP8266WebServer.h>
  14. using WebServerClass = ESP8266WebServer;
  15. #elif defined(ARDUINO_ARCH_ESP32)
  16. #include <WiFi.h>
  17. #include <WebServer.h>
  18. #include <SPIFFS.h>
  19. using WebServerClass = WebServer;
  20. #endif
  21. #include <AutoConnect.h>
  22. /*
  23. AC_USE_SPIFFS indicates SPIFFS or LittleFS as available file systems that
  24. will become the AUTOCONNECT_USE_SPIFFS identifier and is exported as shown
  25. the valid file system. After including AutoConnect.h, the Sketch can determine
  26. whether to use FS.h or LittleFS.h by AUTOCONNECT_USE_SPIFFS definition.
  27. */
  28. #include <FS.h>
  29. #if defined(ARDUINO_ARCH_ESP8266)
  30. #ifdef AUTOCONNECT_USE_SPIFFS
  31. FS& FlashFS = SPIFFS;
  32. #else
  33. #include <LittleFS.h>
  34. FS& FlashFS = LittleFS;
  35. #endif
  36. #elif defined(ARDUINO_ARCH_ESP32)
  37. #include <SPIFFS.h>
  38. fs::SPIFFSFS& FlashFS = SPIFFS;
  39. #endif
  40. #define CONFIG_FILE "/elements.json"
  41. #define USERNAME "username_you_wish" // For HTTP authentication
  42. #define PASSWORD "password_you_wish" // For HTTP authentication
  43. static const char PAGE_ELEMENTS[] PROGMEM = R"(
  44. {
  45. "uri": "/elements",
  46. "title": "Elements",
  47. "menu": true,
  48. "element": [
  49. {
  50. "name": "tablecss",
  51. "type": "ACStyle",
  52. "value": "table{font-family:arial,sans-serif;border-collapse:collapse;width:100%;color:black;}td,th{border:1px solid #dddddd;text-align:center;padding:8px;}tr:nth-child(even){background-color:#dddddd;}"
  53. },
  54. {
  55. "name": "text",
  56. "type": "ACText",
  57. "value": "AutoConnect element behaviors collection",
  58. "style": "font-family:Arial;font-size:18px;font-weight:400;color:#191970"
  59. },
  60. {
  61. "name": "check",
  62. "type": "ACCheckbox",
  63. "value": "check",
  64. "label": "Check",
  65. "labelposition": "infront",
  66. "checked": true
  67. },
  68. {
  69. "name": "input",
  70. "type": "ACInput",
  71. "label": "Text input",
  72. "placeholder": "This area accepts hostname patterns",
  73. "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])$"
  74. },
  75. {
  76. "name": "pass",
  77. "type": "ACInput",
  78. "label": "Password",
  79. "apply": "password"
  80. },
  81. {
  82. "name": "number",
  83. "type": "ACInput",
  84. "label": "Number",
  85. "value": "3",
  86. "apply": "number",
  87. "pattern": "\\d*"
  88. },
  89. {
  90. "name": "hr",
  91. "type": "ACElement",
  92. "value": "<hr style=\"height:1px;border-width:0;color:gray;background-color:#52a6ed\">",
  93. "posterior": "par"
  94. },
  95. {
  96. "name": "radio",
  97. "type": "ACRadio",
  98. "value": [
  99. "Button-1",
  100. "Button-2",
  101. "Button-3"
  102. ],
  103. "label": "Radio buttons",
  104. "arrange": "vertical",
  105. "checked": 1
  106. },
  107. {
  108. "name": "select",
  109. "type": "ACSelect",
  110. "option": [
  111. "Option-1",
  112. "Option-2",
  113. "Option-3"
  114. ],
  115. "label": "Select",
  116. "selected": 2
  117. },
  118. {
  119. "name": "table",
  120. "type": "ACElement",
  121. "value": "<table><tr><th>Board</th><th>Platform</th></tr><tr><td>NodeMCU</td><td>Espressif8266</td></tr><tr><td>ESP32-DevKitC</td><td>Espressif32</td></tr></table>",
  122. "posterior": "par"
  123. },
  124. {
  125. "name": "upload",
  126. "type": "ACFile",
  127. "label": "Upload:",
  128. "store": "fs"
  129. },
  130. {
  131. "name": "load",
  132. "type": "ACSubmit",
  133. "value": "Load",
  134. "uri": "/elements"
  135. },
  136. {
  137. "name": "save",
  138. "type": "ACSubmit",
  139. "value": "Save",
  140. "uri": "/save"
  141. },
  142. {
  143. "name": "adjust_width",
  144. "type": "ACElement",
  145. "value": "<script type=\"text/javascript\">window.onload=function(){var t=document.querySelectorAll(\"input[type='text']\");for(i=0;i<t.length;i++){var e=t[i].getAttribute(\"placeholder\");e&&t[i].setAttribute(\"size\",e.length*.8)}};</script>"
  146. }
  147. ]
  148. }
  149. )";
  150. static const char PAGE_SAVE[] PROGMEM = R"(
  151. {
  152. "uri": "/save",
  153. "title": "Elements",
  154. "menu": false,
  155. "element": [
  156. {
  157. "name": "caption",
  158. "type": "ACText",
  159. "format": "Elements have been saved to %s",
  160. "style": "font-family:Arial;font-size:18px;font-weight:400;color:#191970"
  161. },
  162. {
  163. "name": "validated",
  164. "type": "ACText",
  165. "style": "color:red"
  166. },
  167. {
  168. "name": "echo",
  169. "type": "ACText",
  170. "style": "font-family:monospace;font-size:small;white-space:pre;"
  171. },
  172. {
  173. "name": "ok",
  174. "type": "ACSubmit",
  175. "value": "OK",
  176. "uri": "/elements"
  177. }
  178. ]
  179. }
  180. )";
  181. WebServerClass server;
  182. AutoConnect portal(server);
  183. AutoConnectConfig config;
  184. AutoConnectAux elementsAux;
  185. AutoConnectAux saveAux;
  186. void setup() {
  187. delay(1000);
  188. Serial.begin(115200);
  189. Serial.println();
  190. // Responder of root page handled directly from WebServer class.
  191. server.on("/", []() {
  192. String content = "Place the root page with the sketch application.&ensp;";
  193. content += AUTOCONNECT_LINK(COG_24);
  194. server.send(200, "text/html", content);
  195. });
  196. // Load a custom web page described in JSON as PAGE_ELEMENT and
  197. // register a handler. This handler will be invoked from
  198. // AutoConnectSubmit named the Load defined on the same page.
  199. elementsAux.load(FPSTR(PAGE_ELEMENTS));
  200. elementsAux.on([] (AutoConnectAux& aux, PageArgument& arg) {
  201. if (portal.where() == "/elements") {
  202. // Use the AutoConnect::where function to identify the referer.
  203. // Since this handler only supports AutoConnectSubmit called the
  204. // Load, it uses the uri of the custom web page placed to
  205. // determine whether the Load was called me or not.
  206. FlashFS.begin();
  207. File param = FlashFS.open(CONFIG_FILE, "r");
  208. if (param) {
  209. aux.loadElement(param, { "text", "check", "input", "input", "pass", "number", "radio", "select" } );
  210. param.close();
  211. }
  212. FlashFS.end();
  213. }
  214. return String();
  215. });
  216. saveAux.load(FPSTR(PAGE_SAVE));
  217. saveAux.on([] (AutoConnectAux& aux, PageArgument& arg) {
  218. // You can validate input values ​​before saving with
  219. // AutoConnectInput::isValid function.
  220. // Verification is using performed regular expression set in the
  221. // pattern attribute in advance.
  222. AutoConnectInput& input = elementsAux["input"].as<AutoConnectInput>();
  223. aux["validated"].value = input.isValid() ? String() : String("Input data pattern missmatched.");
  224. // The following line sets only the value, but it is HTMLified as
  225. // formatted text using the format attribute.
  226. aux["caption"].value = CONFIG_FILE;
  227. #if defined(ARDUINO_ARCH_ESP8266)
  228. FlashFS.begin();
  229. #elif defined(ARDUINO_ARCH_ESP32)
  230. FlashFS.begin(true);
  231. #endif
  232. File param = FlashFS.open(CONFIG_FILE, "w");
  233. if (param) {
  234. // Save as a loadable set for parameters.
  235. elementsAux.saveElement(param, { "text", "check", "input", "pass", "number", "radio", "select" });
  236. param.close();
  237. // Read the saved elements again to display.
  238. param = FlashFS.open(CONFIG_FILE, "r");
  239. aux["echo"].value = param.readString();
  240. param.close();
  241. }
  242. else {
  243. aux["echo"].value = "Filesystem failed to open.";
  244. }
  245. FlashFS.end();
  246. return String();
  247. });
  248. portal.join({ elementsAux, saveAux });
  249. config.auth = AC_AUTH_BASIC;
  250. config.authScope = AC_AUTHSCOPE_AUX;
  251. config.username = USERNAME;
  252. config.password = PASSWORD;
  253. config.ticker = true;
  254. portal.config(config);
  255. portal.begin();
  256. }
  257. void loop() {
  258. portal.handleClient();
  259. }