mirror of
https://github.com/marcelstoer/nodemcu-pyflasher.git
synced 2025-07-19 17:26:34 +00:00
Major upgrade of all components
- wxPython 4.0.1, finally... - Python 3 - esptool.py 2.2.1
This commit is contained in:
parent
13961407fe
commit
d837c4b696
13
About.py
13
About.py
@ -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>© 2017 Marcel Stör. Licensed under MIT.</p>
|
<p>© 2018 Marcel Stö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
|
||||||
|
@ -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
32
Main.py
@ -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()
|
||||||
|
|
||||||
|
@ -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')
|
||||||
|
@ -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,
|
||||||
|
37
esptool.py
37
esptool.py
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user