{"id":109647,"date":"2022-03-25T15:48:15","date_gmt":"2022-03-25T15:48:15","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=109647"},"modified":"2024-11-20T11:09:54","modified_gmt":"2024-11-20T11:09:54","slug":"esp32-esp8266-micropython-ota-updates","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-ota-updates\/","title":{"rendered":"ESP32\/ESP8266: MicroPython OTA Updates via PHP Server"},"content":{"rendered":"\n<p>In this project, we&#8217;ll show you an example of how you can do OTA (over-the-air) updates to your ESP32\/ESP8266 boards running MicroPython code via a PHP server. In summary, you&#8217;ll create a PHP server in which you can submit a new code that you want to run on the ESP. When there is a new code\/update available, the ESP downloads the new code, reboots, and starts running the newly downloaded code.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-PHP-Server.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 NodeMCU MicroPython OTA Updates via PHP Server\" class=\"wp-image-109692\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-PHP-Server.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-PHP-Server.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-PHP-Server.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-PHP-Server.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgray\">This project was created by one of our readers: <em>David Flory<\/em>. Thank you for your contributions. He provided the example codes and some explanations, and we&#8217;re documenting the whole process in this tutorial.<\/p>\n\n\n\n<p class=\"rntbox rntclblue\"><strong>Note<\/strong>: for the latest version of his OTA project, please <a href=\"https:\/\/github.com\/david-flory\/Moonlight-Systems\/tree\/eb8a7d7e5132df9f51f650c0ada2e977c3846953\/Projects\/OTA\" target=\"_blank\" rel=\"noopener\" title=\"\">check this repository on his GitHub page<\/a>.<\/p>\n\n\n\n<p class=\"rntbox rntclblue\">Not familiar with MicroPython? <a href=\"https:\/\/randomnerdtutorials.com\/getting-started-micropython-esp32-esp8266\/\">Start here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>OTA (Over-the-Air) update is the process of loading new firmware to the ESP32 or ESP8266 board using a Wi-Fi connection rather than a serial communication. This functionality is extremely useful in case of no physical access to the board.<\/p>\n\n\n\n<p>There are different ways to perform OTA updates. We have <a href=\"https:\/\/randomnerdtutorials.com\/?s=OTA\">several examples for OTA updates using the ESP32\/ESP8266 boards with Arduino IDE<\/a>. In this tutorial, we&#8217;ll create a PHP server that will host new\/updated code. The ESP will periodically communicate with the server to check if there is a new updated code available and download it to the board if that&#8217;s the case.<\/p>\n\n\n\n<p>The following diagram explains how everything works.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"496\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/micropython-OTA-updates-how-it-works-ESP32-ESP8266.png?resize=750%2C496&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 OTA micropython PHP server\" class=\"wp-image-109725\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/micropython-OTA-updates-how-it-works-ESP32-ESP8266.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/micropython-OTA-updates-how-it-works-ESP32-ESP8266.png?resize=300%2C198&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<ol class=\"wp-block-list\">\n<li>The ESP32 or ESP8266 executes whatever tasks you define.<\/li>\n\n\n\n<li>Meanwhile, you upload a new python file that you want to run on your ESP to the Rpi PHP server.<\/li>\n\n\n\n<li>The ESP checks for updates periodically by making a request to the get_ESP_data.php URL to search for a new <span class=\"rnthl rntliteral\">program.py<\/span>.<\/li>\n\n\n\n<li>If there is a new file available, the ESP will download it to its filesystem and reboot.<\/li>\n\n\n\n<li>When it restarts, it will be running the newly uploaded python file.<\/li>\n\n\n\n<li>This new file has an instruction at the beginning of the code to make a request to the <span class=\"rnthl rntliteral\">delete_ESP_data.php<\/span> URL to delete the python file from the PHP server because it is already running the most updated code.<\/li>\n\n\n\n<li>When you upload a new code, the process repeats. Note that the new python file must also contain the instructions to delete the previous file from the PHP server and to check for updates.<\/li>\n<\/ol>\n\n\n\n<p><strong>Alternative method:<\/strong><\/p>\n\n\n\n<p>Here&#8217;s an alternative method that doesn&#8217;t require deleting previous files and allows you to update multiple boards.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The ESP32 or ESP8266 executes whatever tasks you define.<\/li>\n\n\n\n<li>\u00a0The files you upload have a version number on the name.<\/li>\n\n\n\n<li>The URL for updates is taken directly from the new program you upload (it should indicate what the next uploaded file will be called).<\/li>\n\n\n\n<li>You don&#8217;t need to delete any files because all versions have a unique name. So, multiple boards running the same code can update themselves as we no longer delete the files from code, so the <span class=\"rnthl rntliteral\">delete_ESP_data.php<\/span> file can be removed.<\/li>\n<\/ol>\n\n\n\n<p>We provide the files for this method at the end of the tutorial.<\/p>\n\n\n\n<p><strong>Taking it further:<\/strong><\/p>\n\n\n\n<p>A better way to do it might be to create an SQL database on your server, with a record for each ESP with fields for ID (could be MAC address), the version running, time file downloaded (instructions not included).<\/p>\n\n\n\n<p>The PHP could be adjusted to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ask for ID;<\/li>\n\n\n\n<li>Supply the update;<\/li>\n\n\n\n<li>Update the record for the ESP making the request.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before proceeding, make sure you check the following prerequisites.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1) MicroPython Programming<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"250\" height=\"254\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/Micropython-logo.svg-Copy.png?resize=250%2C254&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"MicroPython Logo\" class=\"wp-image-75088\" style=\"width:188px;height:191px\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/Micropython-logo.svg-Copy.png?w=250&amp;quality=100&amp;strip=all&amp;ssl=1 250w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/Micropython-logo.svg-Copy.png?resize=80%2C80&amp;quality=100&amp;strip=all&amp;ssl=1 80w\" sizes=\"(max-width: 250px) 100vw, 250px\" \/><\/figure><\/div>\n\n\n<p>In this tutorial, we&#8217;ll program the ESP32\/ESP8266 boards using MicroPython. Your boards must be burned with MicroPython firmware and you must have a MicroPython IDE to program your boards. We&#8217;ll use <a href=\"https:\/\/randomnerdtutorials.com\/getting-started-thonny-micropython-python-ide-esp32-esp8266\/\">Thonny IDE<\/a>, but you can use any other MicroPython-compatible software.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/getting-started-micropython-esp32-esp8266\/\">Getting Started with MicroPython on ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li>Choose a <a href=\"https:\/\/randomnerdtutorials.com\/micropython-ides-esp32-esp8266\/\">MicroPython IDE for ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li>Burn MicroPyhon firmware using the selected IDE<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">2) PHP Server<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"81\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/PHP-logo.svg_.png?resize=150%2C81&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"PHP Logo\" class=\"wp-image-109653\"\/><\/figure><\/div>\n\n\n<p>The ESP will communicate with the PHP server periodically to check if there are any updates (a new file with a new MicroPython code). You can create a local PHP server on a Raspberry Pi, for example, or alternatively, you can create a PHP server on the cloud (hosting + domain name) that can be accessed from anywhere.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Local PHP Server<\/h4>\n\n\n\n<p>For this example, we&#8217;ll create a local PHP server on a Raspberry Pi. So, you also need a Raspberry Pi for this tutorial:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Get a Raspberry Pi Board: <a href=\"https:\/\/makeradvisor.com\/best-raspberry-pi-starter-kits\/\">check the best Raspberry Pi Starter Kits<\/a><\/li>\n<\/ol>\n\n\n\n<p>After getting a Raspberry Pi, follow the next instructions to set it up:<\/p>\n\n\n\n<ol start=\"2\"><li><a href=\"https:\/\/randomnerdtutorials.com\/installing-raspbian-lite-enabling-and-connecting-with-ssh\/\">Install Raspberry Pi OS, Set Up Wi-Fi, Enable and Connect with SSH<\/a><\/li><\/ol>\n\n\n\n<p>We&#8217;ll provide the instructions to create the local PHP server in this tutorial. You&#8217;ll also need a way to upload files to your PHP server remotely. We&#8217;ll use <a href=\"https:\/\/filezilla-project.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Filezilla<\/a>. You can use any other suitable method. <\/p>\n\n\n\n<ol start=\"3\"><li>To download Filezilla, <a href=\"https:\/\/filezilla-project.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">click here and download the FileZilla client<\/a>.<\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Cloud PHP Server<\/h4>\n\n\n\n<p>Alternatively, you can create your PHP server on the cloud using web hosting and a domain name. We recommend <a href=\"https:\/\/randomnerdtutorials.com\/bluehost\" target=\"_blank\" rel=\"noreferrer noopener\">Bluehost <\/a>or <a href=\"https:\/\/randomnerdtutorials.com\/digitalocean\" target=\"_blank\" rel=\"noreferrer noopener\">Digital Ocean<\/a>. This tutorial doesn&#8217;t provide the instructions for this, but if you&#8217;re familiar with hosting your PHP server, you&#8217;ll easily figure out how to do it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">PART 1 &#8211; Creating the PHP Server<\/h2>\n\n\n\n<p>In this tutorial, we&#8217;ll create a local PHP server on a Raspberry Pi. Alternatively, you can create a cloud PHP server (instructions not included).<\/p>\n\n\n\n<p>Before proceeding make sure you have <a href=\"https:\/\/randomnerdtutorials.com\/installing-raspbian-lite-enabling-and-connecting-with-ssh\/\">installed the Raspberry Pi OS, set up Wi-Fi and SSH<\/a>.<\/p>\n\n\n\n<p>You can either run the next commands on a Raspberry Pi set as a desktop computer or using an&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/installing-raspbian-lite-enabling-and-connecting-with-ssh\/\">SSH connection<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Updating and Upgrading<\/h3>\n\n\n\n<p>&nbsp;Run the following commands to update your Pi. It will take a few minutes to complete.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:~ $ <strong>sudo apt update &amp;&amp; sudo apt upgrade -y<\/strong><\/code><\/pre>\n\n\n\n<p>Change permissions so that the pi user can make modifications to files.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:~ $ <strong>sudo chown pi:pi*<\/strong><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Installing Apache2<\/h3>\n\n\n\n<p>Next, install Apache2. Apache2 is the most widely used web server software. To install Apache2 on your Raspberry Pi, run the next command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:~ $ <strong>sudo apt install apache2 -y<\/strong><\/code><\/pre>\n\n\n\n<p>That\u2019s it! Apache is now installed. To test your installation, change to the <span class=\"rnthl rntliteral\">\/var\/www\/html<\/span> directory and list the files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:~ $ <strong>cd \/var\/www\/html<\/strong>\npi@raspberrypi:<strong>\/var\/www\/html $ ls -al<\/strong>\nindex.html<\/code><\/pre>\n\n\n\n<p>You should have an&nbsp;<em>index.html<\/em>&nbsp;file in that folder. To open that page in your browser, you need to know the Raspberry Pi IP address. Use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:\/var\/www\/html $ <strong>hostname -I<\/strong><\/code><\/pre>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"501\" height=\"178\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/1-Raspberry-Pi-change-directory-RPi-IP-Address.png?resize=501%2C178&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Raspberry Pi change directory RPi IP Address\" class=\"wp-image-89435\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/1-Raspberry-Pi-change-directory-RPi-IP-Address.png?w=501&amp;quality=100&amp;strip=all&amp;ssl=1 501w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/1-Raspberry-Pi-change-directory-RPi-IP-Address.png?resize=300%2C107&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 501px) 100vw, 501px\" \/><\/figure><\/div>\n\n\n<p>In my case, the Raspberry Pi IP address is 192.168.1.86. If you open your RPi IP address in any browser in your local network, a similar web page should load (<strong>http:\/\/192.168.1.86<\/strong>):<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"840\" height=\"565\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/2-Raspberry-Pi-Apache2-Installed.png?resize=840%2C565&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Raspberry Pi Apache2 Installed\" class=\"wp-image-89436\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/2-Raspberry-Pi-Apache2-Installed.png?w=840&amp;quality=100&amp;strip=all&amp;ssl=1 840w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/2-Raspberry-Pi-Apache2-Installed.png?resize=300%2C202&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/2-Raspberry-Pi-Apache2-Installed.png?resize=768%2C517&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">Installing PHP on Raspberry Pi<\/h3>\n\n\n\n<p>PHP is a server side scripting language. PHP (<strong>H<\/strong>ypertext&nbsp;<strong>P<\/strong>re<strong>p<\/strong>rocessor) is used to develop dynamic web applications. A PHP file contains&nbsp;<span class=\"rnthl rntliteral\">&lt;?php \u2026 ?&gt;<\/span>&nbsp;tags and ends with the extension <span class=\"rnthl rntliteral\">.PHP<\/span>.<\/p>\n\n\n\n<p>To install PHP on Raspberry Pi, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:\/var\/www\/html $ <strong>sudo apt install php -y<\/strong><\/code><\/pre>\n\n\n\n<p>You can remove the&nbsp;<em>index.html<\/em>&nbsp;and create a PHP script to test the installation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:\/var\/www\/html $ <strong>sudo rm index.html<\/strong>\npi@raspberrypi:\/var\/www\/html $ <strong>sudo nano index.php<\/strong><\/code><\/pre>\n\n\n\n<p>In your&nbsp;<em>index.php<\/em>&nbsp;file add the following code to echo the \u201c<strong>hello world<\/strong>\u201d message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php echo \"hello world\"; ?&gt;<\/code><\/pre>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"597\" height=\"354\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/3-Raspberry-Pi-Create-PHP-Test-File-Hello-World.png?resize=597%2C354&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Raspberry Pi Create PHP Test File Hello World\" class=\"wp-image-89437\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/3-Raspberry-Pi-Create-PHP-Test-File-Hello-World.png?w=597&amp;quality=100&amp;strip=all&amp;ssl=1 597w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/3-Raspberry-Pi-Create-PHP-Test-File-Hello-World.png?resize=300%2C178&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 597px) 100vw, 597px\" \/><\/figure><\/div>\n\n\n<p>To save your file: press&nbsp;<strong>Ctrl+X<\/strong>, followed by&nbsp;<strong>y<\/strong>, and press&nbsp;<strong>Enter&nbsp;<\/strong>to exit.<\/p>\n\n\n\n<p>Finally, restart Apache2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:\/var\/www\/html $ <strong>sudo service apache2 restart<\/strong><\/code><\/pre>\n\n\n\n<p>To test if Apache2 is serving&nbsp;<em>.php<\/em>&nbsp;files, open the Raspberry Pi IP address and it should display the \u201c<strong>hello world<\/strong>\u201d message from the&nbsp;<em>index.php<\/em>&nbsp;script created earlier.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"557\" height=\"233\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/4-Raspberry-Pi-test-PHP-File-Hello-World-message-web-browser.png?resize=557%2C233&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Raspberry Pi test PHP File Hello World message web browser\" class=\"wp-image-89438\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/4-Raspberry-Pi-test-PHP-File-Hello-World-message-web-browser.png?w=557&amp;quality=100&amp;strip=all&amp;ssl=1 557w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/09\/4-Raspberry-Pi-test-PHP-File-Hello-World-message-web-browser.png?resize=300%2C125&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 557px) 100vw, 557px\" \/><\/figure><\/div>\n\n\n<p>If everything is working, you can remove <span class=\"rnthl rntliteral\"><em>index.php<\/em><\/span> file from the <span class=\"rnthl rntliteral\">\/var\/www\/html<\/span> directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi:\/var\/www\/html $ <strong>sudo rm index.php<\/strong><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Creating the php server &#8211; get_ESP_data.php<\/h3>\n\n\n\n<p>Now, create a file called <span class=\"rnthl rntliteral\">get_ESP_data.php<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi: <strong>sudo nano get_ESP_data.php<\/strong><\/code><\/pre>\n\n\n\n<p>Enter the following PHP code:<\/p>\n\n\n\n<pre class=\"wp-block-code language-php\"><code>&lt;?php\n  $file = $_GET&#091;'file'];\n  $dir = getcwd();\n  $file = $dir.'\/'.$file;\n  $myfile = fopen($file, \"r\") or die(\"FAIL\");\n  echo file_get_contents($file);\n  fclose($myfile);\n?&gt;<\/code><\/pre>\n\n\n\n<p>Press&nbsp;<strong>Ctrl+X<\/strong>, followed by&nbsp;<strong>y<\/strong>, and press&nbsp;<strong>Enter&nbsp;<\/strong>to exit and save the file. This previous script reads the updated file (new code uploaded to the same directory that those files are located) and echo&#8217;s it back in response to a request made by the ESP when it calls the <span class=\"rnthl rntliteral\">check_for_updates<\/span> function as we&#8217;ll see later on.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating the php server &#8211; delete_ESP_data.php<\/h3>\n\n\n\n<p>Create another file called <span class=\"rnthl rntliteral\">delete_ESP_data.php<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pi@raspberrypi: <strong>sudo nano delete_ESP_data.php<\/strong><\/code><\/pre>\n\n\n\n<p> Enter the following PHP code:<\/p>\n\n\n\n<pre class=\"wp-block-code language-php\"><code>&lt;?php\n  $file = $_GET&#091;'file'];\n  $dir = getcwd();\n  $file = $dir.'\/'.$file;\n  unlink($file);\n?&gt;<\/code><\/pre>\n\n\n\n<p>Press&nbsp;<strong>Ctrl+X<\/strong>, followed by&nbsp;<strong>y<\/strong>, and press&nbsp;<strong>Enter&nbsp;<\/strong>to exit and save the file. This file will delete the update file from the PHP server after the ESP has downloaded it.<\/p>\n\n\n\n<p>That&#8217;s it. The PHP server is created and able to echo a new file to the ESP and delete it in response to different requests.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">PART 2 &#8211; Programming the ESP32\/ESP8266<\/h2>\n\n\n\n<p>Before proceeding make sure you burned your boards with MicroPython firmware.<\/p>\n\n\n\n<p>To test the PHP server and integrate it with the ESP boards to make OTA updates, we&#8217;ll show you a simple example. This example needs three files: <span class=\"rnthl rntliteral\"><em>boot.py<\/em><\/span>, <span class=\"rnthl rntliteral\"><em>main.py<\/em><\/span>, and <span class=\"rnthl rntliteral\"><em>program.py<\/em><\/span>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">boot.py<\/h3>\n\n\n\n<p>Using your favorite MicroPython IDE, create a file called <span class=\"rnthl rntliteral\"><em>boot.py<\/em><\/span> with the following content and upload it to your board.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># OTA updater for ESP32 running Micropython by David Flory\r\n# Tutorial: https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-ota-updates\/\r\n\r\ntry:\r\n  import usocket as socket\r\nexcept:\r\n  import socket\r\n\r\ntry:\r\n  import urequests as requests\r\nexcept:\r\n  import requests\r\nimport os \r\nimport sys\r\nimport esp\r\nesp.osdebug(None)\r\nimport gc\r\ngc.collect()\r\nfrom utime import sleep\r\nfrom utime import sleep_ms\r\nimport network\r\n\r\nOTA = 0<\/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\/OTA_Updates_PHP\/boot.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>This file imports the required libraries for network connection. It also creates a boolean variable called <span class=\"rnthl rntliteral\">OTA<\/span> that indicates whether it&#8217;s time to perform an OTA update (download the new file from the PHP server).<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>OTA = 0<\/code><\/pre>\n\n\n\n<p>The ESP runs the <em>boot.py<\/em> first. The first time it runs, there aren&#8217;t any available updates, so we set the <span class=\"rnthl rntliteral\">OTA<\/span> variable to 0.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">main.py<\/h3>\n\n\n\n<p>Create a file called <span class=\"rnthl rntliteral\"><em>main.py<\/em><\/span> with the following content and upload it to your board. You need to modify the file to include your own network credentials and the PHP server URL for the updates.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\">\r\n&quot;&quot;&quot;\r\nOTA updater for ESP32 running Micropython by David Flory.\r\nTutorial: https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-ota-updates\/\r\n\r\nThis is a simple way to run a python program on the ESP32 and download updates or a different program\r\nto run from an HTTP server, either from the web or your local network.\r\n\r\nPut all the imports needed for internet in boot, plus a global variable called OTA\r\nThe main file creates the internet connection then runs whatever program is required. I call the program 'program.py'\r\n\r\nprogram.py is the main program, and can be whatever you want. The only requisite for this to work with OTA is that\r\nit must be imported into the module 'main' and it must check periodically for updates.\r\nThe Program should have a function that can be called by 'main' to start it.\r\n\r\nWe can overwrite program.py while it is running, because it has been imported on boot into the namespace of 'main'.\r\nAll that is required is a reboot after a new Program.py is downloaded. In this case the deep sleep function will reboot the ESP32.\r\n\r\n&quot;&quot;&quot;\r\n#When prog.py finishes, if OTA = True, main downloads it and overwrites program.py, then effectively reboots.\r\n#If OTA is false main just exits.\r\n\r\n#this is the program to be executed. Note we do not use the '.py' extension.\r\nimport program\r\n\r\nimport machine #needed for the deep sleep function\r\n\r\n#URLs for the updates\r\n#replace with your PHP server URL or local IP address (Raspberry Pi IP Address)\r\nupd_url=&quot;http:\/\/192.168.1.XXX\/get_ESP_data.php?file=program.py&quot;\r\n\r\n\r\n#change your wifi credentials here. \r\nssid = 'REPLACE_WITH_YOUR_SSID'\r\npassword = 'REPLACE_WITH_YOUR_PASSWORD'\r\n\r\nprint('OTA is ' + str(OTA))#debug\r\n\r\n#here we set up the network connection\r\nstation = network.WLAN(network.STA_IF)\r\nstation.active(False)\r\nstation.active(True)\r\n#station.config(reconnects = 5)\r\n\r\nstation.connect(ssid,password)\r\n\r\nwhile station.isconnected() == False:\r\n  pass\r\n\r\n#print board local IP address\r\nprint(station.ifconfig())\r\n\r\nif OTA == 0:\r\n    print('starting program')\r\n    OTA = program.mainprog(OTA)\r\n    \r\n#mainprog() is the starting function for my program. OTA is set to 0 on boot so the first time this code\r\n#is run, it sets up the network connection and then runs the program.\r\n#The following code only runs when program.py exits with OTA = 1\r\n\r\nif OTA == 1:\r\n    print('Downloading update')\r\n    #download the update and overwrite program.py\r\n    response = requests.get(upd_url)\r\n    x = response.text.find(&quot;FAIL&quot;)\r\n    if x &gt; 15:\r\n        #download twice and compare for security\r\n        x = response.text\r\n        response = requests.get(upd_url)\r\n        if response.text == x:\r\n            f = open(&quot;program.py&quot;,&quot;w&quot;)\r\n            f.write(response.text)\r\n            f.flush()\r\n            f.close\r\n            \r\n            #soft reboot \r\n            print('reboot now')\r\n            machine.deepsleep(5000)\r\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\/OTA_Updates_PHP\/main.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Here&#8217;s a summary of what this file does:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>connects your board to the internet;<\/li>\n\n\n\n<li>runs your program tasks (whatever you define in the <span class=\"rnthl rntliteral\">program.py<\/span> file we&#8217;ll take a look later)<\/li>\n\n\n\n<li>when you&#8217;re done with your tasks, if there is an updated, it will download it and overwrite the existing <span class=\"rnthl rntliteral\">program.py<\/span> file<\/li>\n\n\n\n<li>after that, it goes into deep sleep for a few seconds;<\/li>\n\n\n\n<li>after waking from deep sleep, it starts all over again with the new downloaded code (OTA update successful).<\/li>\n<\/ul>\n\n\n\n<p>Let&#8217;s take a quick look at the code.<\/p>\n\n\n\n<p>The following line imports the <span class=\"rnthl rntliteral\">program.py&gt;<\/span> file\u2014this is the program to be executed, it must contain the tasks that you want your ESP to do. Note that we <strong>do not use the .py extension<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>import program<\/code><\/pre>\n\n\n\n<p>Then, import the <span class=\"rnthl rntliteral\">machine<\/span> module that is needed for deep sleep function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>import machine<\/code><\/pre>\n\n\n\n<p>Modify the <span class=\"rnthl rntliteral\">upd_url<\/span> variable with your PHP server IP address or URL. In my case, the Raspberry Pi server PHP address is <strong>192.168.1.86<\/strong>, so the <span class=\"rnthl rntliteral\">upd_url<\/span> should be as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>upd_url=\"http:\/\/<strong>192.168.1.86<\/strong>\/get_ESP_data.php?file=program.py\"<\/code><\/pre>\n\n\n\n<p>Insert your network credentials in the following variables, so that the ESP can connect to your network.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>ssid = 'REPLACE_WITH_YOUR_SSID'\npassword = 'REPLACE_WITH_YOUR_PASSWORD'<\/code><\/pre>\n\n\n\n<p>The following line prints the current state of the <span class=\"rnthl rntliteral\">OTA<\/span> variable for debugging purposes.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>print('OTA is ' + str(OTA))<\/code><\/pre>\n\n\n\n<p>The next snippet of code connects the board to your local network and prints its IP address:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>#here we set up the network connection\nstation = network.WLAN(network.STA_IF)\nstation.active(False)\nstation.active(True)\nstation.config(reconnects = 5)\n\nstation.connect(ssid,password)\n\nwhile station.isconnected() == False:\n  pass\n\n#print board local IP address\nprint(station.ifconfig())<\/code><\/pre>\n\n\n\n<p>Finally, it checks the value of the <span class=\"rnthl rntliteral\">OTA<\/span> variable. If it is 0, it runs the main program that contains your tasks (<span class=\"rnthl rntliteral\">main.py<\/span>). <\/p>\n\n\n\n<p><span class=\"rnthl rntliteral\">mainprog()<\/span> is the starting function for our program. <span class=\"rnthl rntliteral\">OTA<\/span> is set to 0 on boot so the first time this code runs, it sets up the network connection and then runs the program.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>if OTA == 0:\n    print('starting program')\n    OTA = program.mainprog(OTA)<\/code><\/pre>\n\n\n\n<p>The following code only runs when <span class=\"rnthl rntliteral\">program.py<\/span> exits with OTA = 1. This section of the code gets the content from the <span class=\"rnthl rntliteral\">program.py<\/span> that is in the PHP server and saves it on the board in the <span class=\"rnthl rntliteral\">program.py<\/span> program, so it overwrites the currently existing <span class=\"rnthl rntliteral\">program.py<\/span> file. After that, it goes to sleep for five seconds (it&#8217;s like a soft reboot). The next time the board reboots, it will run the new code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>if OTA == 1:\n    print('Downloading update')\n    #download the update and overwrite program.py\n    response = requests.get(upd_url)\n    x = response.text.find(\"FAIL\")\n    if x &gt; 15:\n        #download twice and compare for security\n        x = response.text\n        response = requests.get(upd_url)\n        if response.text == x:\n            f = open(\"program.py\",\"w\")\n            f.write(response.text)\n            f.flush()\n            f.close\n            \n            #soft reboot \n            print('reboot now')\n            machine.deepsleep(5000)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">program.py<\/h3>\n\n\n\n<p>Create a file called <span class=\"rnthl rntliteral\">program.py<\/span>. Modify the code to include your local server IP address. Then, upload it to your board. <\/p>\n\n\n\n<p>This is a  simple program to demonstrate OTA update functionality in conjunction with <span class=\"rnthl rntliteral\">main.py<\/span>. The program can be as simple or complicated as you like but must contain these functions: <span class=\"rnthl rntliteral\">check_for_updates()<\/span>, <span class=\"rnthl rntliteral\">mainprog()<\/span> and <span class=\"rnthl rntliteral\">program_tasks()<\/span>.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\">&quot;&quot;&quot;\r\nOTA updater for ESP32 running Micropython by David Flory.\r\nTutorial: https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-ota-updates\/\r\n\r\nA simple program to demonstrate OTA update functionality in conjunction with main.py\r\nThe program can be as simple or complicated as you like, but must contain these functions.\r\nThe variable 'url' should be the full web address to the location of the update file and the PHP script which\r\nreturns it. below is the PHP script, named 'get_ESP_data.php'.\r\n\r\n&lt;?php\r\n    $file = $_GET['file'];\r\n    $dir = getcwd();\r\n    $file = $dir.'\/'.$file;\r\n    $myfile = fopen($file, &quot;r&quot;) or die(&quot;FAIL&quot;);\r\n    echo file_get_contents($file);\r\n    fclose($myfile);\r\n?&gt;\r\n\r\nThe script reads the update file and echo's it back in response to the request made by the\r\n'check_for_updates' function.\r\n\r\nHere is the delete script for deleting the updates.\r\n&lt;?php\r\n    $file = $_GET['file'];\r\n    $dir = getcwd();\r\n    $file = $dir.'\/'.$file;\r\n    unlink($file);\r\n?&gt;\r\n\r\n&quot;&quot;&quot;\r\nimport urequests\r\nfrom utime import sleep\r\n#The URL to use to get updates, full path to the PHP script (Raspberry Pi IP Address). The update file must be in the same\r\n#directory as the PHP script.\r\n#REPLACE WITH YOUR RASPBERRY PI IP ADDRESS\r\nupd_url=&quot;http:\/\/192.168.1.XXX\/get_ESP_data.php?file=program.py&quot;\r\ndel_url = &quot;http:\/\/192.168.1.XXX\/delete_ESP_data.php?file=program.py&quot;\r\n\r\ndef check_for_updates(OTA):\r\n    try:\r\n        #print ('Checking for updates')\r\n        response = urequests.get(upd_url)\r\n        x = response.text.find(&quot;FAIL&quot;)\r\n        if x &gt; 15:\r\n            OTA = 1\r\n            print('There is an update available')\r\n            return(OTA)\r\n        else:\r\n            print('There are no updates available.')\r\n            return(OTA)\r\n\r\n    except:\r\n        print('unable to reach internet')\r\n        return(OTA)\r\n\r\n\r\ndef mainprog(OTA):\r\n    print('Mainprog - OTA is' + str(OTA))\r\n    #This is the entry point for your program code\r\n    #first delete any update files on server. The reasoning here is that if this program is an update we\r\n    #do not want to download it again. If this program is not an update, it is unlikely there will be an\r\n    #update present anyway. If we do not delete it, the program will keep on updating on every loop and rebooting.\r\n    response = urequests.get(del_url)\r\n    print('Program start')\r\n    while OTA == 0:\r\n        program_tasks()\r\n        OTA = check_for_updates(OTA)\r\n        if OTA == 1:\r\n           return(OTA)\r\n        print('OTA = ' + str(OTA))\r\n\r\ndef program_tasks():\r\n    #do program tasks. If continuous loop, use counter or sleep to pass some time between\r\n    #update checks. At your designated point, check for updates.\r\n    sleep(2)\r\n    print('Tasks completed, entering loop 2')\r\n    sleep(2)\r\n    print('Tasks completed, entering loop 3')\r\n    sleep(2)\r\n    print('Tasks completed, entering loop 4')\r\n    sleep(2)\r\n    print('Tasks completed, entering loop 5')\r\n    sleep(2)\r\n    print('5 loops completed, checking for updates')\r\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\/OTA_Updates_PHP\/program_1\/program.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Let&#8217;s take a quick look at the code to see how it works.<\/p>\n\n\n\n<p>First, import any modules that might be required for your tasks. You must include the <span class=\"rnthl rntliteral\">urequests<\/span> library so that the ESP can make requests to the PHP server.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>import urequests\nfrom utime import sleep<\/code><\/pre>\n\n\n\n<p>Update the following variables to include the IP address of your local PHP server or the URL of your cloud web server. Only change the section with the IP address. The rest of the URL should remain as shown.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>upd_url=\"http:\/\/<strong>192.168.1.86<\/strong>\/get_ESP_data.php?file=program.py\"\ndel_url = \"http:\/\/<strong>192.168.1.86<\/strong>\/delete_ESP_data.php?file=program.py\"<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">check_for_updates()<\/span> function checks if there are updates available by making a request on the <span class=\"rnthl rntliteral\">upd_url<\/span>. It returns the <span class=\"rnthl rntliteral\">OTA<\/span> variable value: <span class=\"rnthl rntliteral\">0<\/span> if there aren&#8217;t any updates, or <span class=\"rnthl rntliteral\">1<\/span> if there is an update:<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def check_for_updates(OTA):\n    try:\n        #print ('Checking for updates')\n        response = urequests.get(upd_url)\n        x = response.text.find(\"FAIL\")\n        if x &gt; 15:\n            OTA = 1\n            print('There is an update available')\n            return(OTA)\n        else:\n            print('There are no updates available.')\n            return(OTA)\n\n    except:\n        print('unable to reach internet')\n        return(OTA)<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">mainprog()<\/span> is the entry point for your program code (this function is called on the <span class=\"rnthl rntliteral\">main.py<\/span> file).<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def mainprog(OTA):\n    print('Mainprog - OTA is' + str(OTA))\n    response = urequests.get(del_url)\n    print('Program start')\n    while OTA == 0:\n        program_tasks()\n        OTA = check_for_updates(OTA)\n        if OTA == 1:\n           return(OTA)\n        print('OTA = ' + str(OTA))<\/code><\/pre>\n\n\n\n<p>First, it deletes any update files on the server by making a request on the <span class=\"rnthl rntliteral\">del_url<\/span>. The reasoning here is that if this program is an update we do not want to download it again. If this program is not an update, it is unlikely there will be an update present anyway. If we do not delete it, the program will keep on updating on every loop and rebooting.<\/p>\n\n\n\n<p>Finally, the <span class=\"rnthl rntliteral\">program_tasks()<\/span> function should include the tasks you want to do with your board like sensor readings, data logging, controlling outputs, or any other tasks. For simplicity, we&#8217;re simply printing messages on the MicropPython shell.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>def program_tasks():\n    #do program tasks. If continuous loop, use counter or sleep to pass some time between\n    #update checks. At your designated point, check for updates.\n    sleep(2)\n    print('Tasks completed, entering loop 2')\n    sleep(2)\n    print('Tasks completed, entering loop 3')\n    sleep(2)\n    print('Tasks completed, entering loop 4')\n    sleep(2)\n    print('Tasks completed, entering loop 5')\n    sleep(2)\n    print('5 loops completed, checking for updates')<\/code><\/pre>\n\n\n\n<p>If you&#8217;ll use a continuous loop, use a counter or sleep to pass some time between update checks. At your designated point, check for updates.<\/p>\n\n\n\n<p>If you haven&#8217;t yet, upload all the previous files to your board in this order: <span class=\"rnthl rntliteral\">boot.py<\/span>, <span class=\"rnthl rntliteral\">main.py<\/span> and <span class=\"rnthl rntliteral\">program.py<\/span>. Reset your board so that it starts running the code. It should be printing the following messages on the shell (this is in the <span class=\"rnthl rntliteral\">program_tasks<\/span> function).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"802\" height=\"283\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/Micropython-Shell-OTA.png?resize=802%2C283&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"MicroPython Shell OTA update example\" class=\"wp-image-109689\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/Micropython-Shell-OTA.png?w=802&amp;quality=100&amp;strip=all&amp;ssl=1 802w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/Micropython-Shell-OTA.png?resize=300%2C106&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/Micropython-Shell-OTA.png?resize=768%2C271&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 802px) 100vw, 802px\" \/><\/figure><\/div>\n\n\n<p>Let the board connected to your computer so that we can see on the shell if the updates are successful and for you to understand how it works. This example is solely for demonstration purposes as the aim of OTA is that you don&#8217;t need to have your board connected to your computer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">PART 3 &#8211; Demonstration: OTA Updates<\/h2>\n\n\n\n<p>Now, create a new file also called <span class=\"rnthl rntliteral\">program.py<\/span> and <u>save it on your computer<\/u>. This file will contain the updated code. In our case, we&#8217;ll only change the messages printed on the Shell. We&#8217;ll upload this code over-the-air to your ESP board via the PHP server.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># OTA updater for ESP32 running Micropython by David Flory\r\n# Tutorial: https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-ota-updates\/\r\n\r\n#This program essentially identical to program1, except the tasks are slightly\r\n#different to demonstrate a different program is now running.\r\n\r\nimport urequests\r\nfrom utime import sleep\r\n#The URL to use to get updates, full path to the PHP script (Raspberry Pi IP Address). The update file must be in the same\r\n#directory as the PHP script.\r\n#REPLACE WITH YOUR RASPBERRY PI IP ADDRESS\r\nupd_url=&quot;http:\/\/192.168.1.XXX\/get_ESP_data.php?file=program.py&quot;\r\ndel_url = &quot;http:\/\/192.168.1.XXX\/delete_ESP_data.php?file=program.py&quot;\r\n\r\ndef check_for_updates(OTA):\r\n    try:\r\n        #print ('Checking for updates')\r\n        response = urequests.get(upd_url)\r\n        x = response.text.find(&quot;FAIL&quot;)\r\n        if x &gt; 15:\r\n            OTA = 1\r\n            print('There is an update available')\r\n            return(OTA)\r\n        else:\r\n            print('There are no updates available.')\r\n            return(OTA)\r\n\r\n    except:\r\n        print('unable to reach internet')\r\n        return(OTA)\r\n\r\n\r\ndef mainprog(OTA):\r\n    print('Mainprog - OTA is' + str(OTA))\r\n    #This is the entry point for your program code\r\n    #first delete any update files on server. The reasoning here is that if this program is an update we\r\n    #do not want to download it again. If this program is not an update, it is unlikely there will be an\r\n    #update present anyway. If we do not delete it, the program will keep on updating on every loop and rebooting.\r\n    response = urequests.get(del_url)\r\n    print(response)\r\n    print('Program start')\r\n    while OTA == 0:\r\n        program_tasks()\r\n        OTA = check_for_updates(OTA)\r\n        if OTA == 1:\r\n           return(OTA)\r\n        print('OTA = ' + str(OTA))\r\n\r\ndef program_tasks():\r\n    #do program tasks. If continuous loop, use counter or sleep to pass some time between\r\n    #update checks. At your designated point, check for updates.\r\n    sleep(2)\r\n    print('Updated Program 2, entering loop 2')\r\n    sleep(2)\r\n    print('Updated Program 2, entering loop 3')\r\n    sleep(2)\r\n    print('Updated Program 2, entering loop 4')\r\n    sleep(2)\r\n    print('Updated Program 2, entering loop 5')\r\n    sleep(2)\r\n    print('5 loops completed, checking for updates')\r\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\/OTA_Updates_PHP\/program_2\/program.py\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Note: in a practical application, make sure your code is working properly before making an over-the-air update. If the new code crashes, you might need to connect your board again to your computer to be able to fix the issue.<\/p>\n\n\n\n<p>To upload the new program to the PHP server, we&#8217;ll use Filezilla. You can use any other suitable method\u2014just take into account that you must place the <span class=\"rnthl rntliteral\">program.py<\/span> in the same directory as the PHP files we created previously. If you&#8217;ve followed everything as in the tutorial, the file should be placed on the <span class=\"rnthl rntliteral\">\/var\/www\/html<\/span> directory.<\/p>\n\n\n\n<p>To establish a communication with the Pi, these are the settings (by default):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Host: <strong>raspberrypi<\/strong><\/li>\n\n\n\n<li>Username: <strong>pi<\/strong><\/li>\n\n\n\n<li>Password: <strong>raspberry<\/strong><\/li>\n\n\n\n<li>Port: <strong>22<\/strong><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"716\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-filezilla.jpg?resize=730%2C716&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"MicroPython OTA Updates Filezilla\" class=\"wp-image-109686\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-filezilla.jpg?w=730&amp;quality=100&amp;strip=all&amp;ssl=1 730w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-filezilla.jpg?resize=300%2C294&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 730px) 100vw, 730px\" \/><\/figure><\/div>\n\n\n<p>After uploading the new file to Filezilla, the ESP should detect there is a new file and will download it. Then, it will go into deep sleep, and start running the newly downloaded code. This new code prints a different message than the previous one.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"802\" height=\"770\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/ESP-MicroPython-New-Update-available.png?resize=802%2C770&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 MicroPython OTA Updates via PHP Server Demonstration\" class=\"wp-image-109687\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/ESP-MicroPython-New-Update-available.png?w=802&amp;quality=100&amp;strip=all&amp;ssl=1 802w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/ESP-MicroPython-New-Update-available.png?resize=300%2C288&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/ESP-MicroPython-New-Update-available.png?resize=768%2C737&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 802px) 100vw, 802px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Alternative Method<\/h2>\n\n\n\n<p>As mentioned previously, here&#8217;s an alternative method that doesn&#8217;t require deleting previous files and allows you to update multiple boards.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The ESP32 or ESP8266 executes whatever tasks you define.<\/li>\n\n\n\n<li>\u00a0The files you upload have a version number.<\/li>\n\n\n\n<li>The URL for updates is taken directly from the new program you upload (it should indicate what the next uploaded file will be called).<\/li>\n\n\n\n<li>You don&#8217;t need to delete any files because all versions have a unique name. So, multiple boards running the same code can update themselves as we no longer delete the files from the code, so the <span class=\"rnthl rntliteral\">delete_ESP_data.php<\/span> file can be removed.<\/li>\n\n\n\n<li>Users will have to delete their own files periodically after all boards have been updated.<\/li>\n<\/ol>\n\n\n\n<p>The previous files were modified for this alternative method. Here are the files:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/raw.githubusercontent.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/master\/Projects\/ESP-MicroPython\/OTA_Updates_PHP\/boot.py\" target=\"_blank\" rel=\"noreferrer noopener\">boot.py<\/a> (the same as the previous example)<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/blob\/master\/Projects\/ESP-MicroPython\/OTA_Updates_PHP_Alternative\/main.py\" target=\"_blank\" rel=\"noreferrer noopener\">main.py<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/blob\/master\/Projects\/ESP-MicroPython\/OTA_Updates_PHP_Alternative\/program1.py\" target=\"_blank\" rel=\"noreferrer noopener\">program1.py<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/blob\/master\/Projects\/ESP-MicroPython\/OTA_Updates_PHP_Alternative\/program2.py\" target=\"_blank\" rel=\"noreferrer noopener\">program2.py<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you learned how to update a new code over the air to your ESP32 or ESP8266 boards (programmed with MicroPython) using a PHP server. As an example, we&#8217;ve built a local PHP web server on a Raspberry Pi.<\/p>\n\n\n\n<p>We hope you&#8217;ve found this tutorial useful. If you want to learn more about MicroPython, check out our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266 eBook<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32-esp8266-micropython\/\">Free MicroPython Projects and Tutorials<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this project, we&#8217;ll show you an example of how you can do OTA (over-the-air) updates to your ESP32\/ESP8266 boards running MicroPython code via a PHP server. In summary, you&#8217;ll &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32\/ESP8266: MicroPython OTA Updates via PHP Server\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-micropython-ota-updates\/#more-109647\" aria-label=\"Read more about ESP32\/ESP8266: MicroPython OTA Updates via PHP Server\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":109692,"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":[310,309,264],"tags":[],"class_list":["post-109647","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-micropython","category-0-esp32-micropython","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/03\/MicroPython-OTA-Updates-PHP-Server.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\/109647","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=109647"}],"version-history":[{"count":24,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/109647\/revisions"}],"predecessor-version":[{"id":164097,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/109647\/revisions\/164097"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/109692"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=109647"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=109647"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=109647"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}