diff --git a/code/memanalyzer.py b/code/memanalyzer.py index ee1f6a52..bd38f656 100644 --- a/code/memanalyzer.py +++ b/code/memanalyzer.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -#------------------------------------------------------------------------------- +# coding=utf-8 +# ------------------------------------------------------------------------------- # ESPurna module memory analyser # xose.perez@gmail.com # @@ -11,23 +12,24 @@ # https://github.com/Sermus/ESP8266_memory_analyzer # by Andrey Filimonov # -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- +from __future__ import print_function -from collections import OrderedDict -from sortedcontainers import SortedDict +import argparse +import os +import re import shlex -import commands import subprocess import sys -import os -import re -import argparse +from collections import OrderedDict -#------------------------------------------------------------------------------- +from sortedcontainers import SortedDict -TOTAL_IRAM = 32786; -TOTAL_DRAM = 81920; -env="esp8266-4m-ota" +# ------------------------------------------------------------------------------- + +TOTAL_IRAM = 32786 +TOTAL_DRAM = 81920 +env = "esp8266-4m-ota" objdump_binary = "xtensa-lx106-elf-objdump" sections = OrderedDict([ ("data", "Initialized Data (RAM)"), @@ -38,7 +40,8 @@ sections = OrderedDict([ ]) description = "ESPurna Memory Analyzer v0.1" -#------------------------------------------------------------------------------- + +# ------------------------------------------------------------------------------- def file_size(file): try: @@ -46,8 +49,8 @@ def file_size(file): except: return 0 -def analyse_memory(elf_file): +def analyse_memory(elf_file): command = "%s -t '%s' " % (objdump_binary, elf_file) response = subprocess.check_output(shlex.split(command)) if isinstance(response, bytes): @@ -56,59 +59,59 @@ def analyse_memory(elf_file): # print("{0: >10}|{1: >30}|{2: >12}|{3: >12}|{4: >8}".format("Section", "Description", "Start (hex)", "End (hex)", "Used space")); # print("------------------------------------------------------------------------------"); - ret={} - usedRAM = 0 - usedIRAM = 0 - - i = 0 - for (id, descr) in list(sections.items()): - sectionStartToken = " _%s_start" % id - sectionEndToken = " _%s_end" % id - sectionStart = -1 - sectionEnd = -1 + ret = {} + + for (id_, descr) in list(sections.items()): + section_start_token = " _%s_start" % id_ + section_end_token = " _%s_end" % id_ + section_start = -1 + section_end = -1 for line in lines: - if sectionStartToken in line: + if section_start_token in line: data = line.split(' ') - sectionStart = int(data[0], 16) + section_start = int(data[0], 16) - if sectionEndToken in line: + if section_end_token in line: data = line.split(' ') - sectionEnd = int(data[0], 16) + section_end = int(data[0], 16) - if sectionStart != -1 and sectionEnd != -1: + if section_start != -1 and section_end != -1: break - sectionLength = sectionEnd - sectionStart + section_length = section_end - section_start # if i < 3: - # usedRAM += sectionLength + # usedRAM += section_length # if i == 3: - # usedIRAM = TOTAL_IRAM - sectionLength; + # usedIRAM = TOTAL_IRAM - section_length; - ret[id]=sectionLength - # print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id, descr, sectionStart, sectionEnd, sectionLength)) + ret[id_] = section_length + # print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id_, descr, section_start, section_end, section_length)) # i += 1 # print("Total Used RAM : %d" % usedRAM) # print("Free RAM : %d" % (TOTAL_DRAM - usedRAM)) # print("Free IRam : %d" % usedIRAM) - return(ret) + return ret -def run(env, modules): + +def run(env_, modules_): flags = "" - for item in modules.items(): + for item in modules_.items(): flags += "-D%s_SUPPORT=%d " % item - command = "export ESPURNA_BOARD=\"WEMOS_D1_MINI_RELAYSHIELD\"; export ESPURNA_FLAGS=\"%s\"; platformio run --silent --environment %s" % (flags, env) + command = "export ESPURNA_BOARD=\"WEMOS_D1_MINI_RELAYSHIELD\"; export ESPURNA_FLAGS=\"%s\"; platformio run --silent --environment %s" % (flags, env_) subprocess.check_call(command, shell=True) + def modules_get(): - modules = SortedDict() + modules_ = SortedDict() for line in open("espurna/config/arduino.h"): m = re.search(r'(\w*)_SUPPORT', line) if m: - modules[m.group(1)] = 0 - del modules['LLMNR'] - del modules['NETBIOS'] - return modules + modules_[m.group(1)] = 0 + del modules_['LLMNR'] + del modules_['NETBIOS'] + return modules_ + try: @@ -120,23 +123,22 @@ try: args = parser.parse_args() # Hello - print - print description - print - + print() + print(description) + print() # Check xtensa-lx106-elf-objdump is in the path - status, result = commands.getstatusoutput(objdump_binary) + status, result = subprocess.getstatusoutput(objdump_binary) if status != 512: - print "xtensa-lx106-elf-objdump not found, please check it is in your PATH" + print("xtensa-lx106-elf-objdump not found, please check it is in your PATH") sys.exit(1) # Load list of all modules available_modules = modules_get() if args.list > 0: - print "List of available modules:\n" + print("List of available modules:\n") for key, value in available_modules.items(): - print "* " + key - print + print("* " + key) + print() sys.exit(0) # Which modules to test? @@ -150,7 +152,7 @@ try: # Check test modules exist for module in test_modules: if module not in available_modules: - print "Module %s not found" % module + print("Module %s not found" % module) sys.exit(2) # Define base configuration @@ -163,19 +165,19 @@ try: # Show init message if len(test_modules) > 0: - print "Analyzing module(s) %s on top of %s configuration\n" % (", ".join(test_modules), "CORE" if args.core > 0 else "DEFAULT") + print("Analyzing module(s) %s on top of %s configuration\n" % (", ".join(test_modules), "CORE" if args.core > 0 else "DEFAULT")) else: - print "Analyzing %s configuration\n" % ("CORE" if args.core > 0 else "DEFAULT") + print("Analyzing %s configuration\n" % ("CORE" if args.core > 0 else "DEFAULT")) - output_format="{:<20}|{:<11}|{:<11}|{:<11}|{:<11}|{:<11}|{:<12}" + output_format = "{:<20}|{:<11}|{:<11}|{:<11}|{:<11}|{:<11}|{:<12}" print(output_format.format( - "Module", - "Cache IRAM", - "Init RAM", - "R.O. RAM", - "Uninit RAM", - "Flash ROM", - "Binary size" + "Module", + "Cache IRAM", + "Init RAM", + "R.O. RAM", + "Uninit RAM", + "Flash ROM", + "Binary size" )) # Build the core without modules to get base memory usage @@ -183,13 +185,13 @@ try: base = analyse_memory(".pioenvs/%s/firmware.elf" % env) base['size'] = file_size(".pioenvs/%s/firmware.bin" % env) print(output_format.format( - "CORE" if args.core == 1 else "DEFAULT", - base['text'], - base['data'], - base['rodata'], - base['bss'], - base['irom0_text'], - base['size'], + "CORE" if args.core == 1 else "DEFAULT", + base['text'], + base['data'], + base['rodata'], + base['bss'], + base['irom0_text'], + base['size'], )) # Test each module @@ -198,18 +200,18 @@ try: modules[module] = 1 run(env, modules) - results[module]=analyse_memory(".pioenvs/%s/firmware.elf" % env) + results[module] = analyse_memory(".pioenvs/%s/firmware.elf" % env) results[module]['size'] = file_size(".pioenvs/%s/firmware.bin" % env) modules[module] = 0 print(output_format.format( - module, - results[module]['text'] - base['text'], - results[module]['data'] - base['data'], - results[module]['rodata'] - base['rodata'], - results[module]['bss'] - base['bss'], - results[module]['irom0_text'] - base['irom0_text'], - results[module]['size'] - base['size'], + module, + results[module]['text'] - base['text'], + results[module]['data'] - base['data'], + results[module]['rodata'] - base['rodata'], + results[module]['bss'] - base['bss'], + results[module]['irom0_text'] - base['irom0_text'], + results[module]['size'] - base['size'], )) # Test all modules @@ -223,23 +225,23 @@ try: if len(test_modules) > 1: print(output_format.format( - "ALL MODULES", - total['text'] - base['text'], - total['data'] - base['data'], - total['rodata'] - base['rodata'], - total['bss'] - base['bss'], - total['irom0_text'] - base['irom0_text'], - total['size'] - base['size'], + "ALL MODULES", + total['text'] - base['text'], + total['data'] - base['data'], + total['rodata'] - base['rodata'], + total['bss'] - base['bss'], + total['irom0_text'] - base['irom0_text'], + total['size'] - base['size'], )) print(output_format.format( - "TOTAL", - total['text'], - total['data'], - total['rodata'], - total['bss'], - total['irom0_text'], - total['size'], + "TOTAL", + total['text'], + total['data'], + total['rodata'], + total['bss'], + total['irom0_text'], + total['size'], )) except: diff --git a/code/ota.py b/code/ota.py index 1318be38..403235bc 100644 --- a/code/ota.py +++ b/code/ota.py @@ -1,31 +1,40 @@ #!/usr/bin/env python -#------------------------------------------------------------------------------- +# coding=utf-8 +# ------------------------------------------------------------------------------- # ESPurna OTA manager # xose.perez@gmail.com # # Requires PlatformIO Core -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- +from __future__ import print_function -import sys +import argparse import re -import logging import socket -import argparse import subprocess +import sys from time import sleep + from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf -#------------------------------------------------------------------------------- +try: + # noinspection PyUnresolvedReferences + input = raw_input # Python2 +except NameError: + pass # Python3 + +# ------------------------------------------------------------------------------- devices = [] description = "ESPurna OTA Manager v0.1" -#------------------------------------------------------------------------------- + +# ------------------------------------------------------------------------------- def on_service_state_change(zeroconf, service_type, name, state_change): - ''' + """ Callback that adds discovered devices to "devices" list - ''' + """ if state_change is ServiceStateChange.Added: info = zeroconf.get_service_info(service_type, name) @@ -46,10 +55,11 @@ def on_service_state_change(zeroconf, service_type, name, state_change): device['free_space'] = info.properties.get('free_space') devices.append(device) + def list(): - ''' + """ Shows the list of discovered devices - ''' + """ output_format="{:>3} {:<25}{:<25}{:<15}{:<15}{:<30}{:<10}{:<10}{:<10}" print(output_format.format( "#", @@ -79,12 +89,13 @@ def list(): device.get('free_space', ''), )) - print + print() + def get_boards(): - ''' + """ Grabs board types fro hardware.h file - ''' + """ boards = [] for line in open("espurna/config/hardware.h"): m = re.search(r'defined\((\w*)\)', line) @@ -92,10 +103,11 @@ def get_boards(): boards.append(m.group(1)) return sorted(boards) + def flash(): - ''' + """ Grabs info from the user about what device to flash - ''' + """ # Choose the board try: @@ -103,13 +115,13 @@ def flash(): except: index = 0 if index < 0 or len(devices) < index: - print "Board number must be between 1 and %s\n" % str(len(devices)) + print("Board number must be between 1 and %s\n" % str(len(devices))) return None - board = {'board': '', 'ip': '', 'size': 0 , 'auth': '', 'flags': ''} + board = {'board': '', 'ip': '', 'size': 0, 'auth': '', 'flags': ''} if index > 0: - device = devices[index-1] + device = devices[index - 1] board['board'] = device.get('device', '') board['ip'] = device.get('ip', '') board['size'] = int(device.get('mem_size', 0) if device.get('mem_size', 0) == device.get('sdk_size', 0) else 0) / 1024 @@ -117,68 +129,64 @@ def flash(): # Choose board type if none before if len(board['board']) == 0: - print + print() count = 1 boards = get_boards() for name in boards: - print "%3d\t%s" % (count, name) + print("%3d\t%s" % (count, name)) count = count + 1 - print - + print() try: index = int(input("Choose the board type you want to flash: ")) except: index = 0 if index < 1 or len(boards) < index: - print "Board number must be between 1 and %s\n" % str(len(boards)) + print("Board number must be between 1 and %s\n" % str(len(boards))) return None - board['board'] = boards[index-1] + board['board'] = boards[index - 1] # Choose board size of none before if board['size'] == 0: try: board['size'] = int(input("Board memory size (1 for 1M, 4 for 4M): ")) except: - print "Wrong memory size" + print("Wrong memory size") return None # Choose IP of none before if len(board['ip']) == 0: try: - board['ip'] = raw_input("IP of the device to flash (empty for 192.168.4.1): ") or "192.168.4.1" + board['ip'] = input("IP of the device to flash (empty for 192.168.4.1): ") or "192.168.4.1" except: - print "Wrong IP" + print("Wrong IP") return None - board['auth'] = raw_input("Authorization key of the device to flash: ") - board['flags'] = raw_input("Extra flags for the build: ") + board['auth'] = input("Authorization key of the device to flash: ") + board['flags'] = input("Extra flags for the build: ") return board + def run(device, env): command = "export ESPURNA_IP=\"%s\"; export ESPURNA_BOARD=\"%s\"; export ESPURNA_AUTH=\"%s\"; export ESPURNA_FLAGS=\"%s\"; platformio run --silent --environment %s -t upload" command = command % (device['ip'], device['board'], device['auth'], device['flags'], env) subprocess.check_call(command, shell=True) -#------------------------------------------------------------------------------- + +# ------------------------------------------------------------------------------- if __name__ == '__main__': # Parse command line options parser = argparse.ArgumentParser(description=description) - #parser.add_argument("-v", "--verbose", help="show verbose output", default=0, action='count') parser.add_argument("-c", "--core", help="flash ESPurna core", default=0, action='count') parser.add_argument("-f", "--flash", help="flash device", default=0, action='count') parser.add_argument("-s", "--sort", help="sort devices list by field", default='hostname') args = parser.parse_args() - print - print description - print - - # Enable logging if verbose - #logging.basicConfig(level=logging.DEBUG) - #logging.getLogger('zeroconf').setLevel(logging.DEBUG) + print() + print(description) + print() # Look for sevices zeroconf = Zeroconf() @@ -193,7 +201,7 @@ if __name__ == '__main__': # Sort list field = args.sort.lower() if field not in devices[0]: - print "Unknown field '%s'\n" % field + print("Unknown field '%s'\n" % field) sys.exit(1) devices = sorted(devices, key=lambda device: device.get(field, '')) @@ -212,14 +220,14 @@ if __name__ == '__main__': env = "esp8266-%sm-ota" % device['size'] # Summary - print - print "ESPURNA_IP = %s" % device['ip'] - print "ESPURNA_BOARD = %s" % device['board'] - print "ESPURNA_AUTH = %s" % device['auth'] - print "ESPURNA_FLAGS = %s" % device['flags'] - print "ESPURNA_ENV = %s" % env - - response = raw_input("\nAre these values right [y/N]: ") - print + print() + print("ESPURNA_IP = %s" % device['ip']) + print("ESPURNA_BOARD = %s" % device['board']) + print("ESPURNA_AUTH = %s" % device['auth']) + print("ESPURNA_FLAGS = %s" % device['flags']) + print("ESPURNA_ENV = %s" % env) + + response = input("\nAre these values right [y/N]: ") + print() if response == "y": run(device, env)