From 18f0a9999a0cda20f5f132b3fd839354008ca001 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 11 Nov 2015 23:23:25 +0200 Subject: [PATCH 1/3] add progress option for espota.py and fix typo in ArduinoOTA --- libraries/ArduinoOTA/ArduinoOTA.cpp | 2 +- tools/espota.py | 48 ++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/libraries/ArduinoOTA/ArduinoOTA.cpp b/libraries/ArduinoOTA/ArduinoOTA.cpp index 5833d2f5bc..995c0f4f47 100644 --- a/libraries/ArduinoOTA/ArduinoOTA.cpp +++ b/libraries/ArduinoOTA/ArduinoOTA.cpp @@ -63,7 +63,7 @@ void ArduinoOTAClass::begin() { if (!_hostname.length()) { char tmp[15]; - sprintf(tmp, "esp8266-%02x", ESP.getChipId()); + sprintf(tmp, "esp8266-%06x", ESP.getChipId()); _hostname = tmp; } if (!_port) { diff --git a/tools/espota.py b/tools/espota.py index c03e1c4a70..0aa3a7509a 100755 --- a/tools/espota.py +++ b/tools/espota.py @@ -35,7 +35,33 @@ FLASH = 0 SPIFFS = 100 AUTH = 200 - +PROGRESS = 0 +# update_progress() : Displays or updates a console progress bar +## Accepts a float between 0 and 1. Any int will be converted to a float. +## A value under 0 represents a 'halt'. +## A value at 1 or bigger represents 100% +def update_progress(progress): + if (PROGRESS == 1): + barLength = 60 # Modify this to change the length of the progress bar + status = "" + if isinstance(progress, int): + progress = float(progress) + if not isinstance(progress, float): + progress = 0 + status = "error: progress var must be float\r\n" + if progress < 0: + progress = 0 + status = "Halt...\r\n" + if progress >= 1: + progress = 1 + status = "Done...\r\n" + block = int(round(barLength*progress)) + text = "\rUploading: [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), int(progress*100), status) + sys.stderr.write(text) + sys.stderr.flush() + else: + sys.stderr.write('.') + sys.stderr.flush() def serve(remoteAddr, remotePort, password, filename, command = FLASH): # Create a TCP/IP socket @@ -115,13 +141,17 @@ def serve(remoteAddr, remotePort, password, filename, command = FLASH): try: f = open(filename, "rb") - sys.stderr.write('Uploading') - sys.stderr.flush() + if (PROGRESS == 0): + sys.stderr.write('Uploading') + sys.stderr.flush() + else: + update_progress(0) + offset = 0 while True: chunk = f.read(1460) if not chunk: break - sys.stderr.write('.') - sys.stderr.flush() + offset += len(chunk) + update_progress(offset/float(content_size)) connection.settimeout(10) try: connection.sendall(chunk) @@ -220,6 +250,12 @@ def parser(): action = "store_true", default = False ) + group.add_option("-r", "--progress", + dest = "progress", + help = "Show progress output. Does not work for ArduinoIDE", + action = "store_true", + default = False + ) parser.add_option_group(group) (options, args) = parser.parse_args() @@ -244,6 +280,8 @@ def main(args): logging.debug("Options: %s", str(options)) # check options + if (options.progress): + PROGRESS = 1 if (not options.esp_ip or not options.image): logging.critical("Not enough arguments.") From 0213dc34ff3ffd5fbe8b8f023fd4c1c64847c49a Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 12 Nov 2015 03:09:04 +0200 Subject: [PATCH 2/3] Skip authentication when password is empty should have been changed when turned in String --- libraries/ArduinoOTA/ArduinoOTA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ArduinoOTA/ArduinoOTA.cpp b/libraries/ArduinoOTA/ArduinoOTA.cpp index 995c0f4f47..744c208cc1 100644 --- a/libraries/ArduinoOTA/ArduinoOTA.cpp +++ b/libraries/ArduinoOTA/ArduinoOTA.cpp @@ -199,7 +199,7 @@ void ArduinoOTAClass::handle() { #endif _udp_ota.beginPacket(_ota_ip, _udp_ota.remotePort()); - if (_password){ + if (_password.length()){ MD5Builder nonce_md5; nonce_md5.begin(); nonce_md5.add(String(micros())); From d1235f0204af56612ea89afe47982259cb846d72 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 12 Nov 2015 03:25:20 +0200 Subject: [PATCH 3/3] Fix upload progress and randomize the server port randomization is good in cases where the previous port is not yet released by the OS or the server hangs On OS X it's very noticeable if you need to OTA twice in a short time. --- tools/espota.py | 179 ++++++++++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 89 deletions(-) diff --git a/tools/espota.py b/tools/espota.py index 0aa3a7509a..9913f0045c 100755 --- a/tools/espota.py +++ b/tools/espota.py @@ -30,18 +30,19 @@ import optparse import logging import hashlib +import random # Commands FLASH = 0 SPIFFS = 100 AUTH = 200 -PROGRESS = 0 +PROGRESS = False # update_progress() : Displays or updates a console progress bar ## Accepts a float between 0 and 1. Any int will be converted to a float. ## A value under 0 represents a 'halt'. ## A value at 1 or bigger represents 100% def update_progress(progress): - if (PROGRESS == 1): + if (PROGRESS): barLength = 60 # Modify this to change the length of the progress bar status = "" if isinstance(progress, int): @@ -66,7 +67,7 @@ def update_progress(progress): def serve(remoteAddr, remotePort, password, filename, command = FLASH): # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - serverPort = 48266 + serverPort = random.randint(10000,60000) server_address = ('0.0.0.0', serverPort) logging.info('Starting on %s:%s', str(server_address[0]), str(server_address[1])) try: @@ -141,11 +142,11 @@ def serve(remoteAddr, remotePort, password, filename, command = FLASH): try: f = open(filename, "rb") - if (PROGRESS == 0): + if (PROGRESS): + update_progress(0) + else: sys.stderr.write('Uploading') sys.stderr.flush() - else: - update_progress(0) offset = 0 while True: chunk = f.read(1460) @@ -195,108 +196,108 @@ def serve(remoteAddr, remotePort, password, filename, command = FLASH): def parser(): - parser = optparse.OptionParser( - usage = "%prog [options]", - description = "Transmit image over the air to the esp8266 module with OTA support." - ) + parser = optparse.OptionParser( + usage = "%prog [options]", + description = "Transmit image over the air to the esp8266 module with OTA support." + ) - # destination ip and port - group = optparse.OptionGroup(parser, "Destination") - group.add_option("-i", "--ip", - dest = "esp_ip", - action = "store", - help = "ESP8266 IP Address.", - default = False - ) - group.add_option("-p", "--port", - dest = "esp_port", - type = "int", - help = "ESP8266 ota Port. Default 8266", - default = 8266 - ) - parser.add_option_group(group) + # destination ip and port + group = optparse.OptionGroup(parser, "Destination") + group.add_option("-i", "--ip", + dest = "esp_ip", + action = "store", + help = "ESP8266 IP Address.", + default = False + ) + group.add_option("-p", "--port", + dest = "esp_port", + type = "int", + help = "ESP8266 ota Port. Default 8266", + default = 8266 + ) + parser.add_option_group(group) - # auth - group = optparse.OptionGroup(parser, "Authentication") - group.add_option("-a", "--auth", - dest = "auth", - help = "Set authentication password.", - action = "store", - default = "" - ) - parser.add_option_group(group) + # auth + group = optparse.OptionGroup(parser, "Authentication") + group.add_option("-a", "--auth", + dest = "auth", + help = "Set authentication password.", + action = "store", + default = "" + ) + parser.add_option_group(group) - # image - group = optparse.OptionGroup(parser, "Image") - group.add_option("-f", "--file", - dest = "image", - help = "Image file.", - metavar="FILE", - default = None - ) - group.add_option("-s", "--spiffs", - dest = "spiffs", - action = "store_true", - help = "Use this option to transmit a SPIFFS image and do not flash the module.", - default = False - ) - parser.add_option_group(group) + # image + group = optparse.OptionGroup(parser, "Image") + group.add_option("-f", "--file", + dest = "image", + help = "Image file.", + metavar="FILE", + default = None + ) + group.add_option("-s", "--spiffs", + dest = "spiffs", + action = "store_true", + help = "Use this option to transmit a SPIFFS image and do not flash the module.", + default = False + ) + parser.add_option_group(group) - # output group - group = optparse.OptionGroup(parser, "Output") - group.add_option("-d", "--debug", - dest = "debug", - help = "Show debug output. And override loglevel with debug.", - action = "store_true", - default = False - ) - group.add_option("-r", "--progress", - dest = "progress", - help = "Show progress output. Does not work for ArduinoIDE", - action = "store_true", - default = False - ) - parser.add_option_group(group) + # output group + group = optparse.OptionGroup(parser, "Output") + group.add_option("-d", "--debug", + dest = "debug", + help = "Show debug output. And override loglevel with debug.", + action = "store_true", + default = False + ) + group.add_option("-r", "--progress", + dest = "progress", + help = "Show progress output. Does not work for ArduinoIDE", + action = "store_true", + default = False + ) + parser.add_option_group(group) - (options, args) = parser.parse_args() + (options, args) = parser.parse_args() - return options + return options # end parser def main(args): - # get options - options = parser() + # get options + options = parser() - # adapt log level - loglevel = logging.WARNING - if (options.debug): - loglevel = logging.DEBUG - # end if + # adapt log level + loglevel = logging.WARNING + if (options.debug): + loglevel = logging.DEBUG + # end if - # logging - logging.basicConfig(level = loglevel, format = '%(asctime)-8s [%(levelname)s]: %(message)s', datefmt = '%H:%M:%S') + # logging + logging.basicConfig(level = loglevel, format = '%(asctime)-8s [%(levelname)s]: %(message)s', datefmt = '%H:%M:%S') - logging.debug("Options: %s", str(options)) + logging.debug("Options: %s", str(options)) - # check options - if (options.progress): - PROGRESS = 1 - if (not options.esp_ip or not options.image): - logging.critical("Not enough arguments.") + # check options + global PROGRESS + PROGRESS = options.progress + if (not options.esp_ip or not options.image): + logging.critical("Not enough arguments.") - return 1 - # end if + return 1 + # end if - command = FLASH - if (options.spiffs): - command = SPIFFS - # end if + command = FLASH + if (options.spiffs): + command = SPIFFS + # end if - return serve(options.esp_ip, options.esp_port, options.auth, options.image, command) + return serve(options.esp_ip, options.esp_port, options.auth, options.image, command) # end main if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv)) # end if