{"id":76664,"date":"2018-11-01T11:30:08","date_gmt":"2018-11-01T11:30:08","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=76664"},"modified":"2020-07-30T14:18:56","modified_gmt":"2020-07-30T14:18:56","slug":"esp32-esp8266-micropython-web-server","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-web-server\/","title":{"rendered":"ESP32\/ESP8266 MicroPython Web Server &#8211; Control Outputs"},"content":{"rendered":"<p>Learn how to build a web server to control the ESP32 or ESP8266&nbsp;outputs using MicroPython framework. As an example we&#8217;ll build a web server with ON and OFF buttons to control the on-board LED of the ESP32\/ESP8266. We&#8217;ll use sockets and the Python socket API.<\/p>\n<p><!--more--><\/p>\n<p><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter wp-image-76707 size-full\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/esp32-led-server-micropython.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"esp32 web server with micropython on smartphone\" width=\"1200\" height=\"675\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/esp32-led-server-micropython.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/esp32-led-server-micropython.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/esp32-led-server-micropython.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/esp32-led-server-micropython.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/p>\n<h2>Prerequisites<\/h2>\n<p>To program the ESP32 and ESP8266 with MicroPython, we use uPyCraft IDE as a programming environment. Follow the next tutorials to install uPyCraft IDE and flash MicroPython firmware on your board:<\/p>\n<ul>\n<li>Install uPyCraft IDE:&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/install-upycraft-ide-windows-pc-instructions\/\" target=\"_blank\" rel=\"noopener noreferrer\">Windows PC<\/a>,&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/install-upycraft-ide-mac-os-x-instructions\/\" target=\"_blank\" rel=\"noopener noreferrer\">MacOS X<\/a>, or&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/install-upycraft-ide-linux-ubuntu-instructions\/\" target=\"_blank\" rel=\"noopener noreferrer\">Linux Ubuntu<\/a><\/li>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/flash-upload-micropython-firmware-esp32-esp8266\/\" target=\"_blank\" rel=\"noopener noreferrer\">Flash\/Upload MicroPython Firmware to ESP32 and ESP8266<\/a><\/li>\n<\/ul>\n<p>If this is your first time dealing with MicroPython you may find these next tutorials useful:<\/p>\n<ul>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/getting-started-micropython-esp32-esp8266\/\" target=\"_blank\" rel=\"noopener noreferrer\">Getting Started with MicroPython on ESP32 and ESP8266<\/a><\/li>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-basics-esp32-esp8266\/\" target=\"_blank\" rel=\"noopener noreferrer\">MicroPython Programming Basics with ESP32 and ESP8266<\/a><\/li>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-gpios-esp32-esp8266\/\" target=\"_blank\" rel=\"noopener noreferrer\">MicroPython with ESP32 and ESP8266: Interacting with GPIOs<\/a><\/li>\n<\/ul>\n<h3>Parts required<\/h3>\n<p>For this tutorial you need an ESP32 or ESP8266 board:<\/p>\n<ul>\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noopener noreferrer\">ESP32 DEVKIT DOIT board<\/a> &#8211; read&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noopener noreferrer\">ESP32 Development Boards Review and Comparison<\/a><\/li>\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noopener noreferrer\">ESP8266-12E NodeMCU Kit<\/a> &#8211; read&nbsp;<a href=\"https:\/\/makeradvisor.com\/best-esp8266-wi-fi-development-board\/\" target=\"_blank\" rel=\"noopener noreferrer\">Best ESP8266 Wi-Fi Development Board<\/a><\/li>\n<\/ul>\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n<h2>Preparing the Files<\/h2>\n<p>Connect the ESP32 or ESP8266 board to your computer. Open uPyCraft IDE, and go to <strong>Tools<\/strong> &gt; <strong>Serial<\/strong> and select the serial port.<\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" class=\"aligncenter wp-image-74920 size-full\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPyCraft-IDE-Select-Serial-Port-COM5.png?resize=692%2C576&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"uPyCraft IDE selecting serial port\" width=\"692\" height=\"576\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPyCraft-IDE-Select-Serial-Port-COM5.png?w=692&amp;quality=100&amp;strip=all&amp;ssl=1 692w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPyCraft-IDE-Select-Serial-Port-COM5.png?resize=300%2C250&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 692px) 100vw, 692px\" \/><\/p>\n<p>You should see the files on the ESP32\/ESP8266 board on the device folder. By default, when you burn MicroPython firmware, a <em>boot.py<\/em> file is created.<\/p>\n<p>For this project you&#8217;ll need a <em>boot.py<\/em> file and a <em>main.py<\/em> file.&nbsp;The <em>boot.py<\/em> file has the code that only needs to run once on boot. This includes importing libraries, network credentials, instantiating pins, connecting to your network, and other configurations.<\/p>\n<p>The <em>main.py<\/em> file will contain the code that runs the web server to serve files and perform tasks based on the requests received by the client.<\/p>\n<h3>Creating the&nbsp;<em>main.py<\/em>&nbsp;file on your board<\/h3>\n<ol>\n<li>Press the \u201c<strong>New file<\/strong>\u201d button to create a new file.<\/li>\n<\/ol>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" class=\"aligncenter size-full wp-image-75063\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPycraft-ide-tools-menu-new-file.png?resize=135%2C41&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" width=\"135\" height=\"41\"><\/p>\n<ol>\n<li>Press the \u201c<strong>Save file<\/strong>\u201d button to save the file in your computer.<img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-75064\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPycraft-ide-tools-menu-save-file.png?resize=142%2C47&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" width=\"142\" height=\"47\"><\/p>\n<\/li>\n<li>A new window opens, name your file&nbsp;<em>main.py&nbsp;<\/em>and save it in your computer:<\/p>\n<\/li>\n<\/ol>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-75065\" src=\"https:\/\/i1.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/new-file-created-uPyCraft-IDE.png?resize=402%2C112&amp;ssl=1\" sizes=\"(max-width: 402px) 100vw, 402px\" srcset=\"https:\/\/i1.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/new-file-created-uPyCraft-IDE.png?w=402&amp;ssl=1 402w, https:\/\/i1.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/new-file-created-uPyCraft-IDE.png?resize=300%2C84&amp;ssl=1 300w\" alt=\"\" width=\"402\" height=\"112\"><\/p>\n<ol>\n<li>After that, you should see the following in your uPyCraft IDE (the&nbsp;<em>boot.py<\/em>&nbsp;file in your device and a new tab with the<em>&nbsp;main.py<\/em>&nbsp;file):<\/li>\n<\/ol>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-75071\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/main-py-file-created.png?resize=744%2C476&amp;ssl=1\" sizes=\"(max-width: 744px) 100vw, 744px\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/main-py-file-created.png?w=744&amp;ssl=1 744w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/main-py-file-created.png?resize=300%2C192&amp;ssl=1 300w\" alt=\"\" width=\"744\" height=\"476\"><\/p>\n<ol>\n<li>Click the&nbsp;<strong>\u201cDownload and run<\/strong>\u201d button to upload the file to your ESP board:<\/li>\n<\/ol>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-75060\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/uPycraft-ide-tools-menu-download-and-run.png?resize=238%2C45&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" width=\"238\" height=\"45\"><\/p>\n<ol>\n<li>The device directory should now load the&nbsp;<em>main.py<\/em>&nbsp;file. Your ESP has the file&nbsp;<em>main.py&nbsp;<\/em>stored.<\/li>\n<\/ol>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/upload-file-to-esp32.png?resize=824%2C498&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"uPycraft IDE creating main.py file\" width=\"824\" height=\"498\"><\/p>\n<h3>boot.py<\/h3>\n<p>Copy the following code to the ESP32\/ESP8266&nbsp;<em>boot.py<\/em> file.<\/p>\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\"># Complete project details at https:\/\/RandomNerdTutorials.com\n\ntry:\n  import usocket as socket\nexcept:\n  import socket\n\nfrom machine import Pin\nimport network\n\nimport esp\nesp.osdebug(None)\n\nimport gc\ngc.collect()\n\nssid = 'REPLACE_WITH_YOUR_SSID'\npassword = 'REPLACE_WITH_YOUR_PASSWORD'\n\nstation = network.WLAN(network.STA_IF)\n\nstation.active(True)\nstation.connect(ssid, password)\n\nwhile station.isconnected() == False:\n  pass\n\nprint('Connection successful')\nprint(station.ifconfig())\n\nled = Pin(2, Pin.OUT)\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/esp_web_server_boot.py\" target=\"_blank\">View raw code<\/a><\/p>\n<p>As mentioned previously, we create our web server using sockets and the Python socket API. The official documentation imports the <span class=\"rnthl rntliteral\">socket<\/span> library as follows:<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">try:\n  import usocket as socket\nexcept:\n  import socket<\/code><\/pre>\n<p>We need to import the <span class=\"rnthl rntliteral\">Pin<\/span> class from the&nbsp;<span class=\"rnthl rntliteral\">machine<\/span>&nbsp;module to be able to interact with the GPIOs.<\/p>\n<pre class=\"language-python\"><code>from machine import Pin<\/code><\/pre>\n<p>After importing the <span class=\"rnthl rntliteral\">socket<\/span> library, we need to import the <span class=\"rnthl rntliteral\">network<\/span> library. The <span class=\"rnthl rntliteral\">network<\/span> library allows us to connect the ESP32 or ESP8266 to a Wi-Fi network.<\/p>\n<pre class=\"language-python\"><code>import network<\/code><\/pre>\n<p>The following lines turn off vendor OS debugging messages:<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">import esp\nesp.osdebug(None)<\/code><\/pre>\n<p>Then, we run a garbage collector:<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">import gc\ngc.collect()<\/code><\/pre>\n<p>A garbage collector is a form of automatic memory management. This is a way to reclaim memory occupied by objects that are no longer in used by the program. This is useful to save space in the flash memory.<\/p>\n<p>The following variables hold your network credentials:<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">ssid = 'REPLACE_WITH_YOUR_SSID'\npassword = 'replace_with_your_password'<\/code><\/pre>\n<p>You should replace the words highlighted in red with your network SSID and password, so that the ESP is able to connect to your router.<\/p>\n<p>Then, set the ESP32 or ESP8266 as a Wi-Fi station:<\/p>\n<pre class=\"language-python\"><code>station = network.WLAN(network.STA_IF)<\/code><\/pre>\n<p>After that, activate the station:<\/p>\n<pre class=\"language-python\"><code>station.active(True)<\/code><\/pre>\n<p>Finally, the ESP32\/ESP8266 connects to your router using the SSID and password defined earlier:<\/p>\n<pre class=\"language-python\"><code>station.connect(ssid, password)<\/code><\/pre>\n<p>The following statement ensures that the code doesn\u2019t proceed while the ESP is not connected to your network.<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">while station.isconnected() == False:\n  pass<\/code><\/pre>\n<p>After a successful connection, print network interface parameters like the ESP32\/ESP8266 IP address \u2013 use the <span class=\"rnthl rntliteral\">ifconfig()<\/span> method on the <span class=\"rnthl rntliteral\">station<\/span> object.<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">print('Connection successful')\nprint(station.ifconfig())<\/code><\/pre>\n<p>Create a&nbsp;<span class=\"rnthl rntliteral\">Pin<\/span> object&nbsp;called&nbsp;<span class=\"rnthl rntliteral\">led<\/span> that is an output, that refers to the ESP32\/ESP8266 GPIO2:<\/p>\n<pre class=\"language-python\"><code>led = Pin(2, Pin.OUT)<\/code><\/pre>\n<h3>main.py<\/h3>\n<p>Copy the following code to the ESP32\/ESP8266&nbsp;<em>main.py<\/em> file.<\/p>\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\"># Complete project details at https:\/\/RandomNerdTutorials.com\n\ndef web_page():\n  if led.value() == 1:\n    gpio_state=&quot;ON&quot;\n  else:\n    gpio_state=&quot;OFF&quot;\n  \n  html = &quot;&quot;&quot;&lt;html&gt;&lt;head&gt; &lt;title&gt;ESP Web Server&lt;\/title&gt; &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n  &lt;link rel=&quot;icon&quot; href=&quot;data:,&quot;&gt; &lt;style&gt;html{font-family: Helvetica; display:inline-block; margin: 0px auto; text-align: center;}\n  h1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display: inline-block; background-color: #e7bd3b; border: none; \n  border-radius: 4px; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}\n  .button2{background-color: #4286f4;}&lt;\/style&gt;&lt;\/head&gt;&lt;body&gt; &lt;h1&gt;ESP Web Server&lt;\/h1&gt; \n  &lt;p&gt;GPIO state: &lt;strong&gt;&quot;&quot;&quot; + gpio_state + &quot;&quot;&quot;&lt;\/strong&gt;&lt;\/p&gt;&lt;p&gt;&lt;a href=&quot;\/?led=on&quot;&gt;&lt;button class=&quot;button&quot;&gt;ON&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\n  &lt;p&gt;&lt;a href=&quot;\/?led=off&quot;&gt;&lt;button class=&quot;button button2&quot;&gt;OFF&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;&lt;\/body&gt;&lt;\/html&gt;&quot;&quot;&quot;\n  return html\n\ns = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\ns.bind(('', 80))\ns.listen(5)\n\nwhile True:\n  conn, addr = s.accept()\n  print('Got a connection from %s' % str(addr))\n  request = conn.recv(1024)\n  request = str(request)\n  print('Content = %s' % request)\n  led_on = request.find('\/?led=on')\n  led_off = request.find('\/?led=off')\n  if led_on == 6:\n    print('LED ON')\n    led.value(1)\n  if led_off == 6:\n    print('LED OFF')\n    led.value(0)\n  response = web_page()\n  conn.send('HTTP\/1.1 200 OK\\n')\n  conn.send('Content-Type: text\/html\\n')\n  conn.send('Connection: close\\n\\n')\n  conn.sendall(response)\n  conn.close()\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-MicroPython\/esp_web_server_main.py\" target=\"_blank\">View raw code<\/a><\/p>\n<p>The script starts by creating a function called <span class=\"rnthl rntliteral\">web_page()<\/span>. This function returns a variable called <span class=\"rnthl rntliteral\">html<\/span> that contains the HTML text to build the web page.<\/p>\n<pre class=\"language-python\"><code>def web_page():<\/code><\/pre>\n<p>The web page displays the current GPIO state. So, before generating the HTML text, we need to check the LED state. We save its state on the <span class=\"rnthl rntliteral\">gpio_state<\/span> variable:<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">if led.value() == 1:\n  gpio_state=\"ON\"\nelse:\n  gpio_state=\"OFF\"<\/code><\/pre>\n<p>After that, the <span class=\"rnthl rntliteral\">gpio_state<\/span> variable is incorporated into the HTML text using &#8220;+&#8221; signs to concatenate strings.<\/p>\n<pre>html = \"\"\"&lt;html&gt;&lt;head&gt; &lt;title&gt;ESP Web Server&lt;\/title&gt; &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\n&lt;link rel=\"icon\" href=\"data:,\"&gt; &lt;style&gt;html{font-family: Helvetica; display:inline-block; margin: 0px auto; text-align: center;}\nh1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display: inline-block; background-color: #e7bd3b; border: none; \nborder-radius: 4px; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}\n.button2{background-color: #4286f4;}&lt;\/style&gt;&lt;\/head&gt;&lt;body&gt; &lt;h1&gt;ESP Web Server&lt;\/h1&gt; \n&lt;p&gt;GPIO state: &lt;strong&gt;\"\"\" + <strong>gpio_state<\/strong> + \"\"\"&lt;\/strong&gt;&lt;\/p&gt;&lt;p&gt;&lt;a href=\"\/?led=on\"&gt;&lt;button class=\"button\"&gt;ON&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\n&lt;p&gt;&lt;a href=\"\/?led=off\"&gt;&lt;button class=\"button button2\"&gt;OFF&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;&lt;\/body&gt;&lt;\/html&gt;\"\"\"<\/pre>\n<h3>Creating a socket server<\/h3>\n<p>After creating the HTML to build the web page, we need to create a listening socket to listen for incoming requests and send the HTML text in response. For a better understanding, the following figure shows a diagram on how to create sockets for server-client interaction:<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-76666\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/socket-server.png?resize=394%2C515&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"python socket server and client\" width=\"394\" height=\"515\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/socket-server.png?w=688&amp;quality=100&amp;strip=all&amp;ssl=1 688w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/socket-server.png?resize=229%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 229w\" sizes=\"(max-width: 394px) 100vw, 394px\" \/><\/p>\n<p>Create a socket using <span class=\"rnthl rntliteral\">socket.socket()<\/span>, and specify the socket type. We create a new socket object called <span class=\"rnthl rntliteral\">s<\/span> with the given address family, and socket type. This is a STREAM TCP socket:<\/p>\n<pre class=\"language-python\"><code>s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)<\/code><\/pre>\n<p>Next, bind the socket to an address (network interface and port number) using the <span class=\"rnthl rntliteral\">bind()<\/span> method. The <span class=\"rnthl rntliteral\">bind()<\/span> method accepts a tupple variable with the ip address, and port number:<\/p>\n<pre class=\"language-python\"><code>s.bind(('', 80))<\/code><\/pre>\n<p>In our example, we are passing an empty string &#8216; &#8216; as an IP address and port 80. In this case, the empty string refers to the localhost IP address (this means the ESP32 or ESP8266 IP address).<\/p>\n<p>The next line enables the server to accept connections; it makes a \u201clistening\u201d socket. The argument specifies the maximum number of queued connections. The maximum is 5.<\/p>\n<pre class=\"language-python\"><code>s.listen(5)<\/code><\/pre>\n<p>In the while loop is where we listen for requests and send responses. When a client connects, the server calls the <span class=\"rnthl rntliteral\">accept()<\/span> method to accept the connection. When a client connects, it saves a new socket object to accept and send data on the <span class=\"rnthl rntliteral\">conn<\/span> variable, and saves the client address to connect to the server on the <span class=\"rnthl rntliteral\">addr<\/span> variable.<\/p>\n<pre class=\"language-python\"><code>conn, addr = s.accept()<\/code><\/pre>\n<p>Then, print the address of the client saved on the <span class=\"rnthl rntliteral\">addr<\/span> variable.<\/p>\n<pre class=\"language-python\"><code>print('Got a connection from %s' % str(addr))<\/code><\/pre>\n<p>The data is exchanged between the client and server using the <span class=\"rnthl rntliteral\">send()<\/span> and <span class=\"rnthl rntliteral\">recv()<\/span> methods.<\/p>\n<p>The following line gets the request received on the newly created socket and saves it in the <span class=\"rnthl rntliteral\">request<\/span> variable.<\/p>\n<pre class=\"language-python\"><code>request = conn.recv(1024)<\/code><\/pre>\n<p>The <span class=\"rnthl rntliteral\">recv()<\/span> method receives the data from the client socket (remember that we\u2019ve created a new socket object on the <span class=\"rnthl rntliteral\">conn<\/span> variable). The argument of the <span class=\"rnthl rntliteral\">recv()<\/span> method specifies the maximum data that can be received at once.<\/p>\n<p>The next line simply prints the content of the request:<\/p>\n<pre class=\"language-python\"><code>print('Content = %s' % str(request))<\/code><\/pre>\n<p>Then, create a variable called <span class=\"rnthl rntliteral\">response<\/span> that contains the HTML text returned by the <span class=\"rnthl rntliteral\">web_page()<\/span> function:<\/p>\n<pre class=\"language-python\"><code>response = web_page()<\/code><\/pre>\n<p>Finally, send the response to the socket client using the <span class=\"rnthl rntliteral\">send()<\/span>&nbsp;and <span class=\"rnthl rntliteral\">sendall()<\/span> methods:<\/p>\n<pre class=\"language-python\"><code class=\"language-python\">conn.send('HTTP\/1.1 200 OK\\n')\nconn.send('Content-Type: text\/html\\n')\nconn.send('Connection: close\\n\\n')\nconn.sendall(response)<\/code><\/pre>\n<p>In the end, close the created socket.<\/p>\n<pre class=\"language-python\"><code>conn.close()<\/code><\/pre>\n<h2>Testing the Web Server<\/h2>\n<p>Upload the <em>main.py<\/em> and <em>boot.py<\/em> files to the ESP32\/ESP8266. Your&nbsp;<em>device<\/em> folder should contain two files: <em>boot.py<\/em> and <em>main.py<\/em>.<\/p>\n<p>After uploading the files, press the ESP EN\/RST on-board button.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-75009 size-full\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-EN-enable-button.jpg?resize=608%2C471&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"esp32 enable button\" width=\"608\" height=\"471\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-EN-enable-button.jpg?w=608&amp;quality=100&amp;strip=all&amp;ssl=1 608w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-EN-enable-button.jpg?resize=300%2C232&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 608px) 100vw, 608px\" \/><\/p>\n<p>After a few seconds, it should establish a connection with your router and print the IP address on the Shell.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-76705\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/ip-address.png?resize=552%2C45&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" width=\"552\" height=\"45\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/ip-address.png?w=552&amp;quality=100&amp;strip=all&amp;ssl=1 552w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/ip-address.png?resize=300%2C24&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 552px) 100vw, 552px\" \/><\/p>\n<p>Open your browser, and type your ESP IP address you&#8217;ve just found. You should see the web server page as shown below.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-76708 size-full\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/micropython-web-server-browser.png?resize=514%2C469&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"esp32 web server control outputs\" width=\"514\" height=\"469\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/micropython-web-server-browser.png?w=514&amp;quality=100&amp;strip=all&amp;ssl=1 514w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/micropython-web-server-browser.png?resize=300%2C274&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 514px) 100vw, 514px\" \/><\/p>\n<p>When you press the ON button, you make a request on the ESP IP address followed by <span class=\"rnthl rntliteral\">\/?led=on<\/span>. The ESP32\/ESP8266 on-board LED turns on, and the GPIO state is updated on the page.<\/p>\n<p><strong>Note:<\/strong> some ESP8266 on-board LEDs turn on the LED with an OFF command, and turn off the LED with the ON command.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-76710 size-full\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/DSC02551.jpg?resize=750%2C500&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"web server on smartphone and esp32\" width=\"750\" height=\"500\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/DSC02551.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/DSC02551.jpg?resize=300%2C200&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/p>\n<p>When you press the OFF button, you make a request on the ESP IP address followed by <span class=\"rnthl rntliteral\">\/?led=off<\/span>. The LED turns off, and the GPIO state is updated.<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-76709\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/DSC02584.jpg?resize=750%2C500&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" width=\"750\" height=\"500\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/DSC02584.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/DSC02584.jpg?resize=300%2C200&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/p>\n<p><strong>Note:<\/strong> to keep this tutorial simple, we&#8217;re controlling the on-board LED that corresponds to GPIO 2. You can control any other GPIO with any other output&nbsp;(a relay, for example) using the same method. Also, you can modify the code to control multiple GPIOs or change the HTML text to create a different web page.<\/p>\n<h2>Wrapping Up<\/h2>\n<p>This tutorial showed you how to build a simple web server with MicroPython firmware to control the ESP32\/ESP8266 GPIOs using sockets and the Python socket library. If you&#8217;re looking for a web server tutorial with Arduino IDE, you can check the following resources:<\/p>\n<ul>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-arduino-ide\/\" target=\"_blank\" rel=\"noopener noreferrer\">ESP32 Web Server \u2013 Arduino IDE<\/a><\/li>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-web-server\/\" target=\"_blank\" rel=\"noopener noreferrer\">ESP8266 Web Server &#8211; Arduino IDE<\/a><\/li>\n<\/ul>\n<p>If you&#8217;re looking for more projects with the ESP32 and ESP8266 boards, you can take a look at the following:<\/p>\n<ul>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\" target=\"_blank\" rel=\"noopener noreferrer\">20+ ESP32 Projects and Tutorials<\/a><\/li>\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\" target=\"_blank\" rel=\"noopener noreferrer\">30+ ESP8266 Projects<\/a><\/li>\n<\/ul>\n<p>We hope you\u2019ve found this article about how to build a web server with MicroPython useful. To learn more about MicroPython, take a look at our eBook: <strong><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266<\/a><\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to build a web server to control the ESP32 or ESP8266&nbsp;outputs using MicroPython framework. As an example we&#8217;ll build a web server with ON and OFF buttons to &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32\/ESP8266 MicroPython Web Server &#8211; Control Outputs\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-web-server\/#more-76664\" aria-label=\"Read more about ESP32\/ESP8266 MicroPython Web Server &#8211; Control Outputs\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":76707,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,309,264,257],"tags":[],"class_list":["post-76664","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-0-esp32-micropython","category-project","category-web-server-2"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/11\/esp32-led-server-micropython.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/76664","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=76664"}],"version-history":[{"count":1,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/76664\/revisions"}],"predecessor-version":[{"id":144646,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/76664\/revisions\/144646"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/76707"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=76664"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=76664"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=76664"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}