{"id":1270,"date":"2016-01-11T15:02:07","date_gmt":"2016-01-11T23:02:07","guid":{"rendered":"http:\/\/internetofhomethings.com\/homethings\/?p=1270"},"modified":"2016-01-11T15:06:56","modified_gmt":"2016-01-11T23:06:56","slug":"triple-server-update-part-2-web-configuration","status":"publish","type":"post","link":"https:\/\/internetofhomethings.com\/homethings\/?p=1270","title":{"rendered":"Triple Server Update &#8211; Part 2: Web Configuration"},"content":{"rendered":"<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/configuration_1452048316.png\" rel=\"attachment wp-att-1272\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1272 size-medium\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/configuration_1452048316-300x300.png\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/configuration_1452048316-300x300.png 300w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/configuration_1452048316-150x150.png 150w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/configuration_1452048316.png 640w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Have you ever moved your ESP8266 system from one Wifi location to another? Or perhaps made an extra one for your friend? In many cases, the initial setup\u00a0requires a change to the sketch, to adjust the Wifi parameters to match the new access point&#8212;that is&#8212;unless the local settings\u00a0are stored in the ESP8266 EEPROM.<\/p>\n<p>What&#8217;s great about the EEPROM is that once updated, the configuration is non-volatile, That is, the values remain the same after the system power is removed and re-applied.<\/p>\n<p>This post provides a method of setting and saving parameters likely to change with WiFi location, without changing the installed firmware sketch.<\/p>\n<p>Once you&#8217;ve got you IoT device finished, you really should\u00a0not have to modify the software again. That is, unless enhancements are made or bugs corrected.<\/p>\n<h3 style=\"text-align: center;\"><strong>Configurable Parameters<\/strong><\/h3>\n<p>I started out with intentions on building a reusable configuration\u00a0template. This would include the parameters most likely to change with system location and cloud-based servers used.<\/p>\n<p>Using the Triple Server sketch I had developed recently as a test case, the configurable network and MQTT parameters \u00a0were first identified. Then, these parameters were mapped to the ESP8266 EEPROM.<\/p>\n<p>For the project presented in this post, the following parameters were singled out to be configurable:<\/p>\n<ul>\n<li>WIFI SSID<\/li>\n<li>WIFI Password<\/li>\n<li>IP &#8211; Static IP assigned to ESP8266 when used in Station mode<\/li>\n<li>NM &#8211; Network Mask<\/li>\n<li>GW &#8211; Gateway (Wifi Router IP)<\/li>\n<li>AP &#8211;\u00a0Static IP assigned to ESP8266 when used in Access Point\u00a0mode<\/li>\n<li>Web Server network port<\/li>\n<li>MQTT Broker<\/li>\n<li>MQTT Username<\/li>\n<li>MQTT Password<\/li>\n<li>MQTT Request Topic<\/li>\n<li>MQTT Reply Topic<\/li>\n<li>Serial Port baud<\/li>\n<li>Arduino Server Enable<\/li>\n<\/ul>\n<h3 style=\"text-align: center;\"><strong>EEPROM Memory Map<\/strong><\/h3>\n<p><span style=\"line-height: 1.5;\">The ESP8266 EEPROM configuration space is typically the first 512 bytes of memory. And here is how I allocated the configurable parameters to this EEPROM.<\/span><\/p>\n<p>[wptg_comparison_table id=&#8221;14&#8243;]<\/p>\n<p>Note that while 32 bytes are allocated for the character array parameters, this size is the maximum; it is not required to use this entire space. But each character array must be terminated in EEPROM with a NULL (0x00) character.<\/p>\n<h3 style=\"text-align: center;\"><strong>Webpage Structure<\/strong><\/h3>\n<p>The next thing needed was a way to construct a webpage for viewing, altering, and saving these configuration parameters. All of the page rendering is done on the client side browser. With this in mind, the web page was developed using only html, css for styling, and Javascript.<\/p>\n<p>In order to conserve program memory, the webpage source is saved into flash memory. Two character arrays were used, one for the html and JavaScript and a separate one for the css styling.<\/p>\n<p>Next time, I am planning to separate out the JavaScript as well for cleaner partitioning. This can easily be done from the example code provided here and is highly encouraged as an exercise.<\/p>\n<p>A token was placed at the top of the html character array for insertion of the css styling. Likewise, tokens have been placed in the Javascript jquery section for each configurable parameter. These tokens are replaced with the values stored in EEPROM prior to sending the completed webpage string to the client browser for rendering.<\/p>\n<p>In this example:<\/p>\n<pre class=\"easycode; title:;lang:;\"> \u00a0\u00a0\u00a0\u00a0$(\"#ssid\").val(\"set_ssid\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0$(\"#password\").val(\"set_pass\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0$(\"#ip_0\").val(\"set_ip0\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0$(\"#ip_1\").val(\"set_ip1\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0$(\"#ip_2\").val(\"set_ip2\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0$(\"#ip_3\").val(\"set_ip3\");\r\n     .\r\n     .\r\n<\/pre>\n<p>set_ssid is the first parameter token, which is replaced with the value read from EEPROM.<\/p>\n<p>Here is what the rendered configuration page looks like:<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/config_page.jpg\" rel=\"attachment wp-att-1307\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1307 size-full\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/config_page.jpg\" alt=\"config_page\" width=\"497\" height=\"745\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/config_page.jpg 497w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/01\/config_page-200x300.jpg 200w\" sizes=\"auto, (max-width: 497px) 100vw, 497px\" \/><\/a><\/p>\n<p>The parameters are structured in html as a form with the two buttons shown.\u00a0The save button is of type &#8220;submit&#8221; which sends all of the parameters back to the ESP8266 as a GET request for saving to the EEPROM.<\/p>\n<p>But this merely saves the values back to EEPROM. Since the startup setup() function has already been run, the saved parameters do not become effect until an ESP8266 reset is performed. That is accomplished either with\u00a0a power cycle or clicking on the &#8220;RESET ESP8266&#8221; button on this configuration page.<\/p>\n<h3 style=\"text-align: center;\"><strong>ESP8266 Webpage Request\/Reply Code<\/strong><\/h3>\n<p>Code was added to the ESP8266 URL request processing algorithm to handle web page requests. This is performed\u00a0in the sketch&#8217;s\u00a0Server_ProcessRequest function. For webpage requests, a slightly different URL format is used than requests to read a sensor.<\/p>\n<p>The familiar example is the URL to get the sensor values:<\/p>\n<p>192.168.0.132:9701\/?request=GetSensors<\/p>\n<p>When we want the ESP8266 to display the configuration page, enter:<\/p>\n<p>192.168.0.132:9701\/config<\/p>\n<p>Note that there is no &#8220;?&#8221; for webpage requests. In order to parse the URL correctly for this case, the SdkWebServer_parse_url_params() function required modification.<\/p>\n<p>Note that while the sketch provided in this example only supports the configuration page, a review of the code should make it obvious how to expand this to support your own custom webpages.<\/p>\n<pre class=\"easycode; title:;lang:;\">\/\/\u00a0--------------------------------------------------------------\r\n\/\/\u00a0Serving\u00a0Web\u00a0Pages\r\n\/\/\u00a0--------------------------------------------------------------\r\n\/\/\r\n\/\/\u00a0-------------\u00a0Load\u00a0Config\u00a0Page\u00a0-------------------------------\r\nif(os_strcmp(pURL_Param-&gt;pParam[0],\u00a0\"config\")==0)\u00a0{\r\n    GetEepromCfg(&amp;WebPage);\r\n\u00a0\u00a0\u00a0\u00a0SdkWebServer_senddata_html(ptrespconn,\u00a0true,\u00a0\r\n                               (char\u00a0*)\u00a0WebPage.c_str());\r\n}\r\n\/\/\u00a0--------------\u00a0Save\u00a0config\u00a0or\u00a0Reset\u00a0ESP8266\u00a0-------------------\r\nif(os_strcmp(pURL_Param-&gt;pParam[0],\u00a0\"ssid\")==0)\u00a0{\r\n    if(os_strcmp(pURL_Param-&gt;pParVal[0],\u00a0\"reset\")==0){\r\n    \/\/\u00a0-------------\u00a0Reset\u00a0ESP8266\u00a0-------------------------------\r\n\u00a0\u00a0\u00a0\u00a0    WebPage\u00a0=\u00a0reinterpret_cast&lt;const\u00a0__FlashStringHelper\u00a0*&gt;\r\n                  (PAGE_WaitAndReset);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SdkWebServer_senddata_html(ptrespconn,\u00a0true,\u00a0\r\n                                   (char\u00a0*)\u00a0WebPage.c_str());\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0os_timer_arm(&amp;ResetEspTimer,\u00a03000,\u00a0false);\u00a0\r\n    }\r\n\u00a0\u00a0\u00a0\u00a0else\u00a0{\r\n        \/\/\u00a0---\u00a0Save\u00a0config\u00a0to\u00a0EEPROM\u00a0and\u00a0reload\u00a0config\u00a0page\u00a0------\r\n        SetEepromCfg((void\u00a0*)pURL_Param);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WebPage\u00a0=\u00a0reinterpret_cast&lt;const\u00a0__FlashStringHelper\u00a0*&gt;\r\n                  (PAGE_WaitAndReload);\u00a0\/\/reload\u00a0config\u00a0page\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SdkWebServer_senddata_html(ptrespconn,\u00a0true,\u00a0(char\u00a0*)\u00a0\r\n        WebPage.c_str());\r\n    }\r\n}<\/pre>\n<p>The first parameter parsed is used to determine the webpage request type. This example only processes 2 possibilities. If the first parameter is &#8220;config&#8221;, the configuration page is rendered.<\/p>\n<p>That is accomplished by building the webpage string. First using the template, and then substituting values\u00a0for the css and parameter tokens. This is all done in the GetEepromCfg() function:<\/p>\n<pre class=\"easycode; title:;lang:;\"> void\u00a0GetEepromCfg(String\u00a0*page)\r\n{\r\n\u00a0\u00a0\u00a0\u00a0*page\u00a0=\u00a0reinterpret_cast&lt;const\u00a0__FlashStringHelper\u00a0*&gt;\r\n            (PAGE_NetCfg);\r\n\u00a0\u00a0\u00a0\u00a0String\u00a0css\u00a0=\u00a0reinterpret_cast&lt;const\u00a0__FlashStringHelper\u00a0*&gt;\r\n                 (PAGE_Style_css);\r\n\u00a0\u00a0\u00a0\u00a0page-&gt;replace(\"ADDSTYLE\",css);\u00a0\r\n\u00a0\u00a0\u00a0\u00a0css\u00a0=\u00a0\"\";\r\n\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0SetCfgPageWithEepromVal(page,\u00a0\"set_ssid\",\u00a0EEPROM_WIFISSID,\u00a0\r\n    EEPROM_CHR);\r\n\u00a0\u00a0\u00a0\u00a0SetCfgPageWithEepromVal(page,\u00a0\"set_pass\",\u00a0EEPROM_WIFIPASS,\u00a0\r\n    EEPROM_CHR);\r\n\u00a0\u00a0\u00a0\u00a0SetCfgPageWithEepromVal(page,\u00a0\"set_ip0\",\u00a0EEPROM_WIFI_IP0,\u00a0\r\n    EEPROM_INT);\r\n\u00a0\u00a0\u00a0\u00a0SetCfgPageWithEepromVal(page,\u00a0\"set_ip1\",\u00a0EEPROM_WIFI_IP1,\u00a0\r\n    EEPROM_INT);\r\n    .\r\n    .<\/pre>\n<p>But if the first parameter is ssid, the value of the parameter must first be read in order to determine what action is requested. That is because the method of returning values to the ESP8266 code for both of the WebPage button is by submitting the form.<\/p>\n<p>When the reset button is clicked, the ssid value is changed to &#8220;reset&#8221; before submitting. In that case (above code),\u00a0as message is displayed indicating the ESP8266 is resetting. Note that a 3-second delay is implemented using a timer before the ESP8266 resets itself. That is necessary to allow time for the reloading of the configuration webpage to complete prior to the reset.<\/p>\n<p>And in the case that the Save button is clicked, the ssid value from the webpage form input is not modified (set to &#8220;reset&#8221;) and thus, the values are simply saved to EEPROM.<\/p>\n<h3 style=\"text-align: center;\"><strong>Webpage\u00a0Expansion<\/strong><\/h3>\n<p>Again, all you need to do is add a suffix to the ESP8266 access url and add your processing code to expand this webpage server:<\/p>\n<p>192.168.0.132:9701\/YOURCUSTOMPAGE<\/p>\n<pre class=\"easycode; title:;lang:;\">if(os_strcmp(pURL_Param-&gt;pParam[0],\u00a0\"YOURCUSTOMPAGE\")==0)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\/\/Do whatever you want here to handle this request\r\n}<\/pre>\n<p>In case you missed part 1, the same code is used for this part 2. It is available on GitHub <a href=\"https:\/\/github.com\/internetofhomethings\/Configurable-Web-Server\" target=\"_blank\">here<\/a>.<\/p>\n<h3 style=\"text-align: center;\"><strong>In Closing<\/strong><\/h3>\n<p>That&#8217;s it. A working framework for saving configuration parameters to ESP8266 EEPROM. And as an added bonus, you have a structure to expand this to render webpages of your own choosing. To control or monitor your own IoT things visually.<\/p>\n<p>Hope you find this information as useful to you as it is for me&#8230;<\/p>\n<h3 style=\"text-align: center;\"><strong>Credits<\/strong><\/h3>\n<p>Developing this example required research and reuse of material found in public domain sources. Special credit must be given to the following source which inspired my effort presented here. It also may be of use to others&#8230;<\/p>\n<p><a href=\"http:\/\/www.esp8266.com\/viewtopic.php?f=29&amp;t=6127#p31994\" target=\"_blank\">MQTT and Easy Web Config &#8211; by &#8220;The Godfather&#8221; &#8211; Posted October 22, 2015<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Have you ever moved your ESP8266 system from one Wifi location to another? Or perhaps made an extra one for your friend? In many cases, the initial setup\u00a0requires a change &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,64,10,19],"tags":[105,102,103,104],"class_list":["post-1270","post","type-post","status-publish","format-standard","hentry","category-alltheposts","category-arduino","category-esp8266","category-internet-of-things","tag-esp8266-eeprom","tag-esp8266-web-configuration","tag-esp8266-webpages","tag-serving-webpages-with-esp8266"],"_links":{"self":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1270","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1270"}],"version-history":[{"count":18,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1270\/revisions"}],"predecessor-version":[{"id":1316,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1270\/revisions\/1316"}],"wp:attachment":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1270"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1270"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1270"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}