Major upgrade of all components

- wxPython 4.0.1, finally...
- Python 3
- esptool.py 2.2.1
This commit is contained in:
Marcel Stör 2018-02-10 00:05:03 +01:00
parent 13961407fe
commit 2eeb9893db
6 changed files with 54 additions and 35 deletions

View File

@ -1,7 +1,9 @@
# coding=utf-8 # coding=utf-8
import sys, os, wx import sys
import os
import wx
import wx.html import wx.html
import wx.lib.wxpTag import wx.lib.wxpTag
import webbrowser import webbrowser
@ -29,10 +31,12 @@ class AboutDlg(wx.Dialog):
<p> <p>
As with everything I offer for free, this is donation-ware. As with everything I offer for free, this is donation-ware.
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HFN4ZMET5XS2Q"><img src="{0}/images/paypal-256.png" width="256" height="88" alt="Donate with PayPal"></a> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HFN4ZMET5XS2Q">
<img src="{0}/images/paypal-256.png" width="256" height="88" alt="Donate with PayPal">
</a>
</p> </p>
<p>&copy; 2017 Marcel St&ouml;r. Licensed under MIT.</p> <p>&copy; 2018 Marcel St&ouml;r. Licensed under MIT.</p>
<p> <p>
<wxp module="wx" class="Button"> <wxp module="wx" class="Button">
@ -57,7 +61,8 @@ class AboutDlg(wx.Dialog):
self.SetClientSize(html.GetSize()) self.SetClientSize(html.GetSize())
self.CentreOnParent(wx.BOTH) self.CentreOnParent(wx.BOTH)
def _get_bundle_dir(self): @staticmethod
def _get_bundle_dir():
# set by PyInstaller, see http://pyinstaller.readthedocs.io/en/v3.2/runtime-information.html # set by PyInstaller, see http://pyinstaller.readthedocs.io/en/v3.2/runtime-information.html
if getattr(sys, 'frozen', False): if getattr(sys, 'frozen', False):
return sys._MEIPASS return sys._MEIPASS

View File

@ -27,4 +27,4 @@ class HtmlPopupTransientWindow(wx.PopupTransientWindow):
def OnLinkClicked(self, link): def OnLinkClicked(self, link):
# get a hold of the PopupTransientWindow to close it # get a hold of the PopupTransientWindow to close it
self.GetParent().GetParent().Dismiss() self.GetParent().GetParent().Dismiss()
webbrowser.open(link.GetHref()) webbrowser.open(link.GetHref())

32
Main.py
View File

@ -1,9 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
import wx import wx
import wx.adv
import wx.lib.inspection import wx.lib.inspection
import wx.lib.mixins.inspection import wx.lib.mixins.inspection
import sys, os
import sys
import os
import esptool import esptool
import threading import threading
import json import json
@ -14,7 +17,7 @@ from esptool import ESPLoader
from esptool import NotImplementedInROMError from esptool import NotImplementedInROMError
from argparse import Namespace from argparse import Namespace
__version__ = "2.2" __version__ = "3.0"
__flash_help__ = ''' __flash_help__ = '''
<p>This setting is highly dependent on your device!<p> <p>This setting is highly dependent on your device!<p>
<p> <p>
@ -50,7 +53,9 @@ class RedirectText:
else: else:
wx.CallAfter(self.__out.AppendText, string) wx.CallAfter(self.__out.AppendText, string)
# noinspection PyMethodMayBeStatic
def flush(self): def flush(self):
# noinspection PyStatementEffect
None None
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -210,7 +215,7 @@ class NodeMcuFlasher(wx.Frame):
reload_button = wx.BitmapButton(panel, id=wx.ID_ANY, bitmap=bmp, reload_button = wx.BitmapButton(panel, id=wx.ID_ANY, bitmap=bmp,
size=(bmp.GetWidth() + 7, bmp.GetHeight() + 7)) size=(bmp.GetWidth() + 7, bmp.GetHeight() + 7))
reload_button.Bind(wx.EVT_BUTTON, on_reload) reload_button.Bind(wx.EVT_BUTTON, on_reload)
reload_button.SetToolTipString("Reload serial device list") reload_button.SetToolTip("Reload serial device list")
file_picker = wx.FilePickerCtrl(panel, style=wx.FLP_USE_TEXTCTRL) file_picker = wx.FilePickerCtrl(panel, style=wx.FLP_USE_TEXTCTRL)
file_picker.Bind(wx.EVT_FILEPICKER_CHANGED, on_pick_file) file_picker.Bind(wx.EVT_FILEPICKER_CHANGED, on_pick_file)
@ -322,7 +327,8 @@ class NodeMcuFlasher(wx.Frame):
break break
count += 1 count += 1
def _get_serial_ports(self): @staticmethod
def _get_serial_ports():
ports = [""] ports = [""]
for port, desc, hwid in sorted(list_ports.comports()): for port, desc, hwid in sorted(list_ports.comports()):
ports.append(port) ports.append(port)
@ -332,7 +338,7 @@ class NodeMcuFlasher(wx.Frame):
self.SetIcon(images.Icon.GetIcon()) self.SetIcon(images.Icon.GetIcon())
def _build_status_bar(self): def _build_status_bar(self):
self.statusBar = self.CreateStatusBar(2, wx.ST_SIZEGRIP) self.statusBar = self.CreateStatusBar(2, wx.STB_SIZEGRIP)
self.statusBar.SetStatusWidths([-2, -1]) self.statusBar.SetStatusWidths([-2, -1])
status_text = "Welcome to NodeMCU PyFlasher %s" % __version__ status_text = "Welcome to NodeMCU PyFlasher %s" % __version__
self.statusBar.SetStatusText(status_text, 0) self.statusBar.SetStatusText(status_text, 0)
@ -356,7 +362,8 @@ class NodeMcuFlasher(wx.Frame):
self.SetMenuBar(self.menuBar) self.SetMenuBar(self.menuBar)
def _get_config_file_path(self): @staticmethod
def _get_config_file_path():
return wx.StandardPaths.Get().GetUserConfigDir() + "/nodemcu-pyflasher.json" return wx.StandardPaths.Get().GetUserConfigDir() + "/nodemcu-pyflasher.json"
# Menu methods # Menu methods
@ -380,13 +387,12 @@ class NodeMcuFlasher(wx.Frame):
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
class MySplashScreen(wx.SplashScreen): class MySplashScreen(wx.adv.SplashScreen):
def __init__(self): def __init__(self):
wx.SplashScreen.__init__(self, images.Splash.GetBitmap(), wx.adv.SplashScreen.__init__(self, images.Splash.GetBitmap(),
wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT, wx.adv.SPLASH_CENTRE_ON_SCREEN | wx.adv.SPLASH_TIMEOUT, 2500, None, -1)
2500, None, -1)
self.Bind(wx.EVT_CLOSE, self._on_close) self.Bind(wx.EVT_CLOSE, self._on_close)
self.__fc = wx.FutureCall(2000, self._show_main) self.__fc = wx.CallLater(2000, self._show_main)
def _on_close(self, evt): def _on_close(self, evt):
# Make sure the default handler runs too so this window gets # Make sure the default handler runs too so this window gets
@ -412,7 +418,7 @@ class MySplashScreen(wx.SplashScreen):
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
class App(wx.App, wx.lib.mixins.inspection.InspectionMixin): class App(wx.App, wx.lib.mixins.inspection.InspectionMixin):
def OnInit(self): def OnInit(self):
wx.SystemOptions.SetOptionInt("mac.window-plain-transition", 1) wx.SystemOptions.SetOption("mac.window-plain-transition", 1)
self.SetAppName("NodeMCU PyFlasher") self.SetAppName("NodeMCU PyFlasher")
# Create and show the splash screen. It will then create and # Create and show the splash screen. It will then create and
@ -435,6 +441,8 @@ def main():
app.MainLoop() app.MainLoop()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
if __name__ == '__main__': if __name__ == '__main__':
__name__ = 'Main' __name__ = 'Main'
main() main()

View File

@ -2,7 +2,6 @@
block_cipher = None block_cipher = None
a = Analysis(['nodemcu-pyflasher.py'], a = Analysis(['nodemcu-pyflasher.py'],
binaries=None, binaries=None,
datas=[("images", "images")], datas=[("images", "images")],
@ -26,6 +25,6 @@ exe = EXE(pyz,
upx=True, upx=True,
console=False , icon='images/icon-256.icns') console=False , icon='images/icon-256.icns')
app = BUNDLE(exe, app = BUNDLE(exe,
name='NodeMCU-PyFlasher.app', name='NodeMCU-PyFlasher-3.0.app',
icon='./images/icon-256.icns', icon='./images/icon-256.icns',
bundle_identifier='com.frightanic.nodemcu-pyflasher') bundle_identifier='com.frightanic.nodemcu-pyflasher')

View File

@ -19,7 +19,7 @@ exe = EXE(pyz,
a.binaries, a.binaries,
a.zipfiles, a.zipfiles,
a.datas, a.datas,
name='NodeMCU-PyFlasher', name='NodeMCU-PyFlasher-3.0',
debug=False, debug=False,
strip=False, strip=False,
upx=True, upx=True,

View File

@ -33,7 +33,7 @@ import zlib
import serial import serial
__version__ = "2.2" __version__ = "2.2.1"
MAX_UINT32 = 0xffffffff MAX_UINT32 = 0xffffffff
MAX_UINT24 = 0xffffff MAX_UINT24 = 0xffffff
@ -183,10 +183,10 @@ class ESPLoader(object):
with ones which throw NotImplementedInROMError(). with ones which throw NotImplementedInROMError().
""" """
if isinstance(port, serial.Serial): if isinstance(port, str):
self._port = port
else:
self._port = serial.serial_for_url(port) self._port = serial.serial_for_url(port)
else:
self._port = port
self._slip_reader = slip_reader(self._port, self.trace) self._slip_reader = slip_reader(self._port, self.trace)
# setting baud rate in a separate step is a workaround for # setting baud rate in a separate step is a workaround for
# CH341 driver on some Linux versions (this opens at 9600 then # CH341 driver on some Linux versions (this opens at 9600 then
@ -265,18 +265,21 @@ class ESPLoader(object):
""" Send a request and read the response """ """ Send a request and read the response """
def command(self, op=None, data=b"", chk=0, wait_response=True, timeout=DEFAULT_TIMEOUT): def command(self, op=None, data=b"", chk=0, wait_response=True, timeout=DEFAULT_TIMEOUT):
if op is not None:
self.trace("command op=0x%02x data len=%s wait_response=%d timeout=%.3f data=%r",
op, len(data), 1 if wait_response else 0, timeout, data)
pkt = struct.pack(b'<BBHI', 0x00, op, len(data), chk) + data
self.write(pkt)
if not wait_response:
return
saved_timeout = self._port.timeout saved_timeout = self._port.timeout
self._port.timeout = min(timeout, MAX_TIMEOUT) new_timeout = min(timeout, MAX_TIMEOUT)
if new_timeout != saved_timeout:
self._port.timeout = new_timeout
try: try:
if op is not None:
self.trace("command op=0x%02x data len=%s wait_response=%d timeout=%.3f data=%r",
op, len(data), 1 if wait_response else 0, timeout, data)
pkt = struct.pack(b'<BBHI', 0x00, op, len(data), chk) + data
self.write(pkt)
if not wait_response:
return
# tries to get a response until that response has the # tries to get a response until that response has the
# same operation as the request or a retries limit has # same operation as the request or a retries limit has
# exceeded. This is needed for some esp8266s that # exceeded. This is needed for some esp8266s that
@ -292,7 +295,8 @@ class ESPLoader(object):
if op is None or op_ret == op: if op is None or op_ret == op:
return val, data return val, data
finally: finally:
self._port.timeout = saved_timeout if new_timeout != saved_timeout:
self._port.timeout = saved_timeout
raise FatalError("Response doesn't match request") raise FatalError("Response doesn't match request")
@ -1839,6 +1843,9 @@ def write_flash(esp, args):
if args.no_stub: if args.no_stub:
print('Erasing flash...') print('Erasing flash...')
image = pad_to(argfile.read(), 4) image = pad_to(argfile.read(), 4)
if len(image) == 0:
print('WARNING: File %s is empty' % argfile.name)
continue
image = _update_image_flash_params(esp, address, args, image) image = _update_image_flash_params(esp, address, args, image)
calcmd5 = hashlib.md5(image).hexdigest() calcmd5 = hashlib.md5(image).hexdigest()
uncsize = len(image) uncsize = len(image)