{"id":1918,"date":"2020-12-21T03:06:33","date_gmt":"2020-12-20T21:36:33","guid":{"rendered":"https:\/\/judepereira.com\/blog\/?p=1918"},"modified":"2020-12-21T03:10:54","modified_gmt":"2020-12-20T21:40:54","slug":"sending-ota-updates-over-wifi-to-your-esp8266","status":"publish","type":"post","link":"https:\/\/judepereira.com\/blog\/sending-ota-updates-over-wifi-to-your-esp8266\/","title":{"rendered":"Sending OTA updates over WiFi to your ESP8266"},"content":{"rendered":"\n<p>This Christmas, I added a whole bunch of lights powered by 5V power sources. My goal was to switch them on at sunset, and switch them off on sunrise, by using a MOSFET for power control :)<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>While I was doing this, I wanted to send OTA updates of my Lua files to the ESP8266 via WiFi. For some unknown reason, I couldn&#8217;t use luatool.py&#8217;s TCP update method. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>So, I ended up building my very own OTA update protocol (which turned out to be fun!). To begin, add <code>ota.lua<\/code> to your project, and invoke it using <code>dofile(\"ota.lua\")<\/code> in your <code>init.lua<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist107033876\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-ota-lua\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-lua  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"ota.lua content, created by judepereira on 09:26PM on December 20, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"ota.lua\">\n        <tr>\n          <td id=\"file-ota-lua-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-ota-lua-LC1\" class=\"blob-code blob-code-inner js-file-line\">&#8212; Send OTA updates to remotely update lua scripts on your ESP8266.<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-ota-lua-LC2\" class=\"blob-code blob-code-inner js-file-line\">&#8212;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-ota-lua-LC3\" class=\"blob-code blob-code-inner js-file-line\">&#8212; LICENCE: http:\/\/opensource.org\/licenses\/MIT<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-ota-lua-LC4\" class=\"blob-code blob-code-inner js-file-line\">&#8212; Created by Jude Pereira &lt;contact@judepereira.com&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-ota-lua-LC5\" class=\"blob-code blob-code-inner js-file-line\">&#8212; See https:\/\/judepereira.com\/blog\/sending-ota-updates-over-wifi-to-your-esp8266\/<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-ota-lua-LC6\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-ota-lua-LC7\" class=\"blob-code blob-code-inner js-file-line\">srv = net.createServer(net.TCP)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-ota-lua-LC8\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-ota-lua-LC9\" class=\"blob-code blob-code-inner js-file-line\">current_file_name = nil<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-ota-lua-LC10\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-ota-lua-LC11\" class=\"blob-code blob-code-inner js-file-line\">srv:listen(8080, function(conn)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-ota-lua-LC12\" class=\"blob-code blob-code-inner js-file-line\">    conn:on(&quot;receive&quot;, function(sck, payload)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-ota-lua-LC13\" class=\"blob-code blob-code-inner js-file-line\">        if string.sub(payload, 1, 5) == &quot;BEGIN&quot; then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-ota-lua-LC14\" class=\"blob-code blob-code-inner js-file-line\">            current_file_name = string.sub(payload, 7)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-ota-lua-LC15\" class=\"blob-code blob-code-inner js-file-line\">            file.open(current_file_name, &quot;w&quot;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-ota-lua-LC16\" class=\"blob-code blob-code-inner js-file-line\">            file.close()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-ota-lua-LC17\" class=\"blob-code blob-code-inner js-file-line\">            sck:send(&quot;NodeMCU: Writing to &quot; .. current_file_name .. &#39;&#8230;\\n&#39;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-ota-lua-LC18\" class=\"blob-code blob-code-inner js-file-line\">        elseif string.sub(payload, 1, 4) == &quot;DONE&quot; then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-ota-lua-LC19\" class=\"blob-code blob-code-inner js-file-line\">            sck:send(&quot;NodeMCU: Wrote file &quot; .. current_file_name .. &quot;!\\n&quot;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-ota-lua-LC20\" class=\"blob-code blob-code-inner js-file-line\">            current_file_name = nil<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-ota-lua-LC21\" class=\"blob-code blob-code-inner js-file-line\">        elseif string.sub(payload, 1, 7) == &quot;RESTART&quot; then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-ota-lua-LC22\" class=\"blob-code blob-code-inner js-file-line\">            sck:send(&quot;NodeMCU: Restart!\\n&quot;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-ota-lua-LC23\" class=\"blob-code blob-code-inner js-file-line\">            tmr.create():alarm(500, tmr.ALARM_SINGLE, node.restart)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-ota-lua-LC24\" class=\"blob-code blob-code-inner js-file-line\">        else<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-ota-lua-LC25\" class=\"blob-code blob-code-inner js-file-line\">            if file.open(current_file_name, &quot;a+&quot;) then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L26\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"26\"><\/td>\n          <td id=\"file-ota-lua-LC26\" class=\"blob-code blob-code-inner js-file-line\">                if file.write(payload) then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L27\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"27\"><\/td>\n          <td id=\"file-ota-lua-LC27\" class=\"blob-code blob-code-inner js-file-line\">                    file.close()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L28\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"28\"><\/td>\n          <td id=\"file-ota-lua-LC28\" class=\"blob-code blob-code-inner js-file-line\">                    sck:send(&quot;ok\\n&quot;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L29\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"29\"><\/td>\n          <td id=\"file-ota-lua-LC29\" class=\"blob-code blob-code-inner js-file-line\">                else<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L30\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"30\"><\/td>\n          <td id=\"file-ota-lua-LC30\" class=\"blob-code blob-code-inner js-file-line\">                    sck:send(&quot;NodeMCU: Write failed!\\n&quot;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L31\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"31\"><\/td>\n          <td id=\"file-ota-lua-LC31\" class=\"blob-code blob-code-inner js-file-line\">                end<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L32\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"32\"><\/td>\n          <td id=\"file-ota-lua-LC32\" class=\"blob-code blob-code-inner js-file-line\">            else<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L33\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"33\"><\/td>\n          <td id=\"file-ota-lua-LC33\" class=\"blob-code blob-code-inner js-file-line\">                sck:send(&quot;NodeMCU: Open failed!\\n&quot;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L34\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"34\"><\/td>\n          <td id=\"file-ota-lua-LC34\" class=\"blob-code blob-code-inner js-file-line\">            end<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L35\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"35\"><\/td>\n          <td id=\"file-ota-lua-LC35\" class=\"blob-code blob-code-inner js-file-line\">        end<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L36\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"36\"><\/td>\n          <td id=\"file-ota-lua-LC36\" class=\"blob-code blob-code-inner js-file-line\">    end)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L37\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"37\"><\/td>\n          <td id=\"file-ota-lua-LC37\" class=\"blob-code blob-code-inner js-file-line\">    conn:on(&quot;sent&quot;, function(sck) sck:close() end)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-lua-L38\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"38\"><\/td>\n          <td id=\"file-ota-lua-LC38\" class=\"blob-code blob-code-inner js-file-line\">end)<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/judepereira\/8f2938395f8ecb76b48899bf0a43b7b4\/raw\/d9991502231ae0728fcd0a4bc005e848ef627e88\/ota.lua\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/judepereira\/8f2938395f8ecb76b48899bf0a43b7b4#file-ota-lua\" class=\"Link--inTextBlock\">\n          ota.lua\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<p>Then, to use this shiny new TCP endpoint created on your ESP8266\/NodeMCU, create a wrapper shell script:<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\n<style>.gist table { margin-bottom: 0; }<\/style><div style=\"tab-size: 8\" id=\"gist107033907\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-ota-sh\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-shell  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"ota.sh content, created by judepereira on 09:29PM on December 20, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https:\/\/github.co\/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"ota.sh\">\n        <tr>\n          <td id=\"file-ota-sh-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-ota-sh-LC1\" class=\"blob-code blob-code-inner js-file-line\">#!\/bin\/bash<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-ota-sh-LC2\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-ota-sh-LC3\" class=\"blob-code blob-code-inner js-file-line\"># Wrapper script for sending OTA updates to your ESP8266 running NodeMCU.<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-ota-sh-LC4\" class=\"blob-code blob-code-inner js-file-line\"># See https:\/\/judepereira.com\/blog\/sending-ota-updates-over-wifi-to-your-esp8266\/<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-ota-sh-LC5\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-ota-sh-LC6\" class=\"blob-code blob-code-inner js-file-line\">HOST=192.168.178.25<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-ota-sh-LC7\" class=\"blob-code blob-code-inner js-file-line\">PORT=8080<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-ota-sh-LC8\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-ota-sh-LC9\" class=\"blob-code blob-code-inner js-file-line\">for i in &quot;$@&quot;; do<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-ota-sh-LC10\" class=\"blob-code blob-code-inner js-file-line\">    FILE=$i<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-ota-sh-LC11\" class=\"blob-code blob-code-inner js-file-line\">    echo &quot;Sending $i&#8230;&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-ota-sh-LC12\" class=\"blob-code blob-code-inner js-file-line\">    echo -n &quot;BEGIN $FILE&quot; | nc $HOST $PORT<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-ota-sh-LC13\" class=\"blob-code blob-code-inner js-file-line\">    while read -r line; do<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-ota-sh-LC14\" class=\"blob-code blob-code-inner js-file-line\">        #echo -n &quot;write: $line &#8230; &quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-ota-sh-LC15\" class=\"blob-code blob-code-inner js-file-line\">        if ! echo &quot;$line&quot; | nc $HOST $PORT | grep &quot;ok&quot; &amp;&gt;\/dev\/null; then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-ota-sh-LC16\" class=\"blob-code blob-code-inner js-file-line\">            echo &quot;Write failed! Please retry&#8230;&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-ota-sh-LC17\" class=\"blob-code blob-code-inner js-file-line\">            exit 1<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-ota-sh-LC18\" class=\"blob-code blob-code-inner js-file-line\">        fi<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-ota-sh-LC19\" class=\"blob-code blob-code-inner js-file-line\">    done &lt;&quot;$FILE&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-ota-sh-LC20\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-ota-sh-LC21\" class=\"blob-code blob-code-inner js-file-line\">    echo -n &quot;DONE&quot; | nc $HOST $PORT<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-ota-sh-LC22\" class=\"blob-code blob-code-inner js-file-line\">done<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-ota-sh-LC23\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-ota-sh-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-ota-sh-LC24\" class=\"blob-code blob-code-inner js-file-line\">echo -n &quot;RESTART&quot; | nc $HOST $PORT<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https:\/\/gist.github.com\/judepereira\/4055040a0b4c602c298b8249801bbd83\/raw\/d74542ae80ca9f19fe3fb85156249e5ad7014658\/ota.sh\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https:\/\/gist.github.com\/judepereira\/4055040a0b4c602c298b8249801bbd83#file-ota-sh\" class=\"Link--inTextBlock\">\n          ota.sh\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https:\/\/github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n\n<\/div><\/figure>\n\n\n\n<p><strong>Heads up!<\/strong> Replace <code>HOST<\/code> with the IP of your NodeMCU.<\/p>\n\n\n\n<p>The wrapper script will automatically trigger a restart at the end. To use the wrapper script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ chmod +x ota.sh\n$ .\/ota.sh file1.lua file2.lua init.lua<\/code><\/pre>\n\n\n\n<p>And that&#8217;s it! OTA update away!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This Christmas, I added a whole bunch of lights powered by 5V power sources. My goal was to switch them on at sunset, and switch them off on sunrise, by using a MOSFET for power control :) While I was doing this, I wanted to send OTA updates of my Lua files to the ESP8266 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","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":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[52,504],"tags":[654,655,652,656,653,657],"class_list":["post-1918","post","type-post","status-publish","format-standard","hentry","category-code","category-hardware","tag-esp8266","tag-nodemcu","tag-ota","tag-remote-updates","tag-update","tag-updates"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pqtyx-uW","jetpack-related-posts":[{"id":1940,"url":"https:\/\/judepereira.com\/blog\/lessons-learnt-from-esp-now\/","url_meta":{"origin":1918,"position":0},"title":"Lessons learnt from ESP NOW","author":"Jude Pereira","date":"February 18, 2021","format":false,"excerpt":"For those of you who aren\u2019t aware of ESP NOW, it\u2019s a communication protocol developed by Espressif for their ESP modules. What began as a simple \u201chook up my plant lights to HomeKit\u201d, turned into a massive home grown firmware, but more about that in another post. I\u2019ve successfully setup\u2026","rel":"","context":"In &quot;hardware&quot;","block_context":{"text":"hardware","link":"https:\/\/judepereira.com\/blog\/category\/hardware\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1648,"url":"https:\/\/judepereira.com\/blog\/openwrt-wont-bring-my-wifi-interface-up-unless-the-other-is-up\/","url_meta":{"origin":1918,"position":1},"title":"OpenWRT won&#8217;t bring my WiFi interface up, unless the other is up","author":"Jude Pereira","date":"September 25, 2015","format":false,"excerpt":"I recently bought a D-Link DIR 505 router. So far, I've got a DLNA server running on it, along with Transmission, a bit torrent client. Life is awesome so far. I set it up to repeat another WiFi router in my house, the one connected to the internet - using\u2026","rel":"","context":"In &quot;another snippet | code&quot;","block_context":{"text":"another snippet | code","link":"https:\/\/judepereira.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":64,"url":"https:\/\/judepereira.com\/blog\/faunos-shadow\/","url_meta":{"origin":1918,"position":2},"title":"FaunOS Shadow","author":"Jude Pereira","date":"January 20, 2009","format":false,"excerpt":"It's a distribution based totally on Arch Linux... specialized for USB Portable installs and can also be used as primary OS has over 600 packages pre-installed (I know... it reminds you of Fedora and me too!). So that's to say that it comes with definitely all the packages you would\u2026","rel":"","context":"In &quot;gnu linux&quot;","block_context":{"text":"gnu linux","link":"https:\/\/judepereira.com\/blog\/category\/linux\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1616,"url":"https:\/\/judepereira.com\/blog\/0f-float-min_value-false\/","url_meta":{"origin":1918,"position":3},"title":"0f > Float.MIN_VALUE = false!","author":"Jude Pereira","date":"April 23, 2015","format":false,"excerpt":"Updates: Turns out that this is the expected behaviour from the java doc: A constant holding the smallest positive nonzero value of type float, 2-149. So now, how do I get the smallest negative value that a float can hold? Just came across the most weirdest thing ever in Java\u2026","rel":"","context":"In &quot;miscellaneous&quot;","block_context":{"text":"miscellaneous","link":"https:\/\/judepereira.com\/blog\/category\/misc\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2126,"url":"https:\/\/judepereira.com\/blog\/upgrading-to-debian-bookworm-on-qnap-ts-112-also-ts-11x-ts-12x\/","url_meta":{"origin":1918,"position":4},"title":"Upgrading to Debian Bookworm on QNAP TS-112 (also TS-11x\/TS-12x)","author":"Jude Pereira","date":"October 16, 2024","format":false,"excerpt":"I decided to host Minio on a QNAP TS-112 device, bought from a second hand store. Here's a tale of me ditching the QNAP OS in favour of Debian Bookworm.","rel":"","context":"In &quot;gnu linux&quot;","block_context":{"text":"gnu linux","link":"https:\/\/judepereira.com\/blog\/category\/linux\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1881,"url":"https:\/\/judepereira.com\/blog\/nrf52840-flash-s340\/","url_meta":{"origin":1918,"position":5},"title":"nRF52840 &#8211; flashing the s340 v6.1.1 SoftDevice","author":"Jude Pereira","date":"July 12, 2019","format":false,"excerpt":"This post is a work in progress (WIP). The result of this experiment is a success. I have flashed my SparkFun nRF52840 mini, and I'm able to run the bicycle combined speed & cadence sensor example. Before we begin, \u00a0a big hats off to\u00a0Charles, who brought support for the SparkFun\u2026","rel":"","context":"In &quot;hardware&quot;","block_context":{"text":"hardware","link":"https:\/\/judepereira.com\/blog\/category\/hardware\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/posts\/1918","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/comments?post=1918"}],"version-history":[{"count":2,"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/posts\/1918\/revisions"}],"predecessor-version":[{"id":1920,"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/posts\/1918\/revisions\/1920"}],"wp:attachment":[{"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/media?parent=1918"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/categories?post=1918"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/judepereira.com\/blog\/wp-json\/wp\/v2\/tags?post=1918"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}