{"id":1190,"date":"2015-11-26T06:28:19","date_gmt":"2015-11-26T14:28:19","guid":{"rendered":"http:\/\/internetofhomethings.com\/homethings\/?p=1190"},"modified":"2015-12-02T20:06:21","modified_gmt":"2015-12-03T04:06:21","slug":"esp8266-arduino-ide-web-server-using-callbacks","status":"publish","type":"post","link":"https:\/\/internetofhomethings.com\/homethings\/?p=1190","title":{"rendered":"ESP8266 Arduino IDE Web Server Using Callbacks"},"content":{"rendered":"<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2015\/11\/sdkcall.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1191\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2015\/11\/sdkcall.jpg\" alt=\"sdkcall\" width=\"552\" height=\"185\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2015\/11\/sdkcall.jpg 552w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2015\/11\/sdkcall-300x101.jpg 300w\" sizes=\"auto, (max-width: 552px) 100vw, 552px\" \/><\/a><\/p>\n<p>While the Arduino IDE is a convenient and familiar platform to develop ESP8266 Web Server based projects, it does have a significant drawback. That is, once the Web Server is started, it is necessary to poll the server each iteration of the loop() function to check for new connections before processing the request.<\/p>\n<p>Putting the check in a loop with other activities, such as reading sensors could and often does result in significant response delays. And possible loss of communication\u00a0due to connection timeouts.<\/p>\n<p>A better approach is to use a callback that fires whenever an external client connects to the ESP8266 server. This frees up the sketch loop() from the task of servicing http request using inefficient polling code.<\/p>\n<p>And callbacks is how a Web Server is implemented using the ESP8266 EspressIf SDK. But why is it missing from the Arduino IDE? I suspect it is because that is the way it is done with Arduino-based systems&#8212;making it both familiar and perhaps suitable for Arduino code reuse with the ESP8266.<\/p>\n<p>But it is not the best solution for new designs.<\/p>\n<p>So that got me thinking&#8230;<\/p>\n<p>Why not customize the typical web server sketch to use\u00a0the SDK callback schema? After all, it is possible to \u00a0call ESP8266 SDK functions from the Arduino IDE. While searching, I could not find any examples of this being done, so I&#8217;ve created one myself.<\/p>\n<p>And here it is&#8230;<\/p>\n<h3 style=\"text-align: center;\"><strong>The SDK Server Architecture<\/strong><\/h3>\n<p>The\u00a0SDK API requires several layers of callbacks in a web server design. Since these callbacks are usable in a sketch without modification, the actual sketch functions included in this example are shown.<\/p>\n<p>First, \u00a0the server must be setup in the sketch setup() routine. This\u00a0initialization code was encapsulated in the following function, &#8220;SdkWebServer_Init()&#8221;, called in setup():<\/p>\n<pre class=\"easycode; title:;lang:;\"> void SdkWebServer_Init(int\u00a0port)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0LOCAL\u00a0struct\u00a0espconn\u00a0esp_conn;\r\n\u00a0\u00a0\u00a0\u00a0LOCAL\u00a0esp_tcp\u00a0esptcp;\r\n\u00a0\u00a0\u00a0\u00a0\/\/Fill\u00a0the\u00a0connection\u00a0structure,\u00a0including\u00a0\"listen\"\u00a0port\r\n\u00a0\u00a0\u00a0\u00a0esp_conn.type\u00a0=\u00a0ESPCONN_TCP;\r\n\u00a0\u00a0\u00a0\u00a0esp_conn.state\u00a0=\u00a0ESPCONN_NONE;\r\n\u00a0\u00a0\u00a0\u00a0esp_conn.proto.tcp\u00a0=\u00a0&amp;esptcp;\r\n\u00a0\u00a0\u00a0\u00a0esp_conn.proto.tcp-&gt;local_port\u00a0=\u00a0port;\r\n\u00a0\u00a0\u00a0\u00a0esp_conn.recv_callback\u00a0=\u00a0NULL;\r\n\u00a0\u00a0\u00a0\u00a0esp_conn.sent_callback\u00a0=\u00a0NULL;\r\n\u00a0\u00a0\u00a0\u00a0esp_conn.reverse\u00a0=\u00a0NULL;\r\n\u00a0\u00a0\u00a0\u00a0\/\/Register\u00a0the\u00a0connection\u00a0timeout(0=no timeout)\r\n\u00a0\u00a0\u00a0\u00a0espconn_regist_time(&amp;esp_conn,0,0);\r\n\u00a0\u00a0\u00a0\u00a0\/\/Register\u00a0connection\u00a0callback\r\n\u00a0\u00a0\u00a0\u00a0espconn_regist_connectcb(&amp;esp_conn, SdkWebServer_listen);\r\n\u00a0\u00a0\u00a0\u00a0\/\/Start\u00a0Listening\u00a0for\u00a0connections\r\n\u00a0\u00a0\u00a0\u00a0espconn_accept(&amp;esp_conn);\u00a0\r\n}<\/pre>\n<p>Upon an external TCP\u00a0connection, the callback &#8220;SdkWebServer_listen&#8221; is executed:<\/p>\n<pre class=\"easycode; title:;lang:;\"> void SdkWebServer_listen(void\u00a0*arg)\r\n{\r\n\u00a0\u00a0\u00a0\u00a0struct\u00a0espconn\u00a0*pesp_conn\u00a0=\u00a0(\u00a0espconn\u00a0*)arg;\r\n\r\n\u00a0\u00a0\u00a0\u00a0espconn_regist_recvcb(pesp_conn, SdkWebServer_recv);\r\n\u00a0\u00a0\u00a0\u00a0espconn_regist_reconcb(pesp_conn, SdkWebServer_recon);\r\n\u00a0\u00a0\u00a0\u00a0espconn_regist_disconcb(pesp_conn, SdkWebServer_discon);\r\n}<\/pre>\n<p>This functions registers 3 connection-specific callbacks:<\/p>\n<ol>\n<li>SdkWebServer_recv &#8211; Called when connection data is received. This callback replaces the polling loop when using the Arduino library.<\/li>\n<li>SdkWebServer_recon &#8211; Called when TCP connection is broken.<\/li>\n<li>SdkWebServer_discon-Called when a TCP connection is closed.<\/li>\n<\/ol>\n<p>The SdkWebServer_recv() function processes http GET and POST requests in a similar manner as the processing in the loop() after\u00a0an Arduino client connection is detected.<\/p>\n<h3 style=\"text-align: center;\"><strong>Putting It All Together<\/strong><\/h3>\n<p>In order to contrast the commonly used\u00a0Arduino Web Server library with the SDK API, I&#8217;ve put together an\u00a0example sketch that supports both web server approaches.\u00a0It&#8217;s on Github:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/github.com\/internetofhomethings\/ESP8266-Arduino-Ide-Web-Server-Using-SDK-API\" target=\"_blank\">ESP8266-12 Arduino IDE Web Server Example\u00a0<\/a><\/p>\n<p>This\u00a0example provide the same functionality with either\u00a0server interface. The selection is made\u00a0prior to building the sketch, using precompilation directives. When possible, the same code is used with both selections. The difference is that the SDK uses callbacks while the Arduino polls for connections.<\/p>\n<p style=\"text-align: left;\">While no additional hardware is needed to run and test the Web Server, this example assumes the ESP8266 circuit from <a href=\"http:\/\/wp.me\/p5NRQ8-8y\" target=\"_blank\">this post<\/a>. But the code will work with any ESP8266 circuit, even with no externally connected sensors or controls. But without the ADC multiplexer from the referenced post, the ADC will simply make the same measurement for each multiplexer setting. Which is just fine for the purposes of this example.<\/p>\n<h3 style=\"text-align: center;\"><strong>Testing the Server From A Web Browser<\/strong><\/h3>\n<p>Since both versions of the Web Server provide the same functionality, the same test can be performed for verification.<\/p>\n<p>You might need to changed the static IP set in this example to match your own LAN subnet. The defaults are currently set to:<\/p>\n<p>IP: 192.168.0.132<\/p>\n<p>Listen Port: 9701<\/p>\n<p>The test url is thus:<\/p>\n<p>192.168.0.132:9701\/?request=GetSensors<\/p>\n<p>And the JSON returned from the Web Server should be in the following format:<\/p>\n<pre>{\r\n\"Ain0\":\"316.00\",\r\n\"Ain1\":\"326.00\",\r\n\"Ain2\":\"325.00\",\r\n\"Ain3\":\"314.00\",\r\n\"Ain4\":\"316.00\",\r\n\"Ain5\":\"163.00\",\r\n\"Ain6\":\"208.00\",\r\n\"Ain7\":\"333.00\",\r\n\"SYS_Heap\":\"25408\",\r\n\"SYS_Time\":\"26\"\r\n}<\/pre>\n<p>And if connected, the server will also support changing the LED on\/off state:<\/p>\n<p>To turn it on, use the URL:<br \/>\n192.168.0.132:9701\/?request=LedOn<\/p>\n<p>And the off URL i:<br \/>\n192.168.0.132:9701\/?request=LedOff<\/p>\n<p>Adding server functionality should be obvious after reviewing the sketch.<\/p>\n<h3 style=\"text-align: center;\"><strong>Conclusions<\/strong><\/h3>\n<p>Using a callback to process Web Server connection requests is far superior to polling. CPU bandwidth is only used in response to client connection events. And with the example framework provided in this post, you can still utilize many of the Arduino sensor libraries without modification.<\/p>\n<p>With a Web Server application, you get the efficiency of the callback with the familiarity of the Arduino IDE.<\/p>\n<p>I hope you find this information useful&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While the Arduino IDE is a convenient and familiar platform to develop ESP8266 Web Server based projects, it does have a significant drawback. That is, once the Web Server is &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,10,19],"tags":[93,94],"class_list":["post-1190","post","type-post","status-publish","format-standard","hentry","category-alltheposts","category-esp8266","category-internet-of-things","tag-esp8266-arduino-ide-web-server-using-callbacks","tag-using-sdk-functions-with-arduino-ide"],"_links":{"self":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1190","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=1190"}],"version-history":[{"count":20,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1190\/revisions"}],"predecessor-version":[{"id":1222,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1190\/revisions\/1222"}],"wp:attachment":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}