From 9fb7fb433f5221746ccedd9899b6e54aaed4b62d Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Mon, 10 Jun 2024 15:31:13 +0200 Subject: [PATCH] Add console control, bugfixes and windows debug build --- .github/workflows/build_windows.yaml | 2 +- BTClockOTA-debug.spec | 39 ++++++++++++++++++++++++++++ app/espota.py | 17 ++++-------- app/fw_updater.py | 9 ++++++- app/main.py | 32 ++++++++++++++++++++--- app/release_checker.py | 6 +++-- 6 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 BTClockOTA-debug.spec diff --git a/.github/workflows/build_windows.yaml b/.github/workflows/build_windows.yaml index 94899de..2525f74 100644 --- a/.github/workflows/build_windows.yaml +++ b/.github/workflows/build_windows.yaml @@ -32,7 +32,7 @@ jobs: run: | docker run --rm \ --volume "${{ github.workspace }}:/src/" \ - --env SPECFILE=./BTClockOTA.spec \ + --env SPECFILE=./BTClockOTA-debug.spec \ batonogov/pyinstaller-windows:latest # - name: Get current block # id: getBlockHeight diff --git a/BTClockOTA-debug.spec b/BTClockOTA-debug.spec new file mode 100644 index 0000000..82b9de4 --- /dev/null +++ b/BTClockOTA-debug.spec @@ -0,0 +1,39 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['app.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=['zeroconf._utils.ipaddress', 'zeroconf._handlers.answers', 'pyserial', 'wx'], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='BTClockOTA-debug', + debug=True, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['update-icon.ico'], +) diff --git a/app/espota.py b/app/espota.py index 487f8ed..a55e5cf 100644 --- a/app/espota.py +++ b/app/espota.py @@ -102,8 +102,8 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, inv_tries = 0 data = "" msg = "Sending invitation to %s " % remote_addr - sys.stderr.write(msg) - sys.stderr.flush() + logging.info(msg) + while inv_tries < 10: inv_tries += 1 sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -111,8 +111,7 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, try: sent = sock2.sendto(message.encode(), remote_address) # noqa: F841 except: # noqa: E722 - sys.stderr.write("failed\n") - sys.stderr.flush() + logging.info("failed\n") sock2.close() logging.error("Host %s Not Found", remote_addr) return 1 @@ -121,11 +120,8 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, data = sock2.recv(37).decode() break except: # noqa: E722 - sys.stderr.write(".") - sys.stderr.flush() +# logging.info(".") sock2.close() - sys.stderr.write("\n") - sys.stderr.flush() if inv_tries == 10: logging.error("No response from the ESP") return 1 @@ -177,8 +173,7 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, if PROGRESS: progress_handler(0) else: - sys.stderr.write("Uploading") - sys.stderr.flush() + logging.info("Uploading") offset = 0 while True: chunk = f.read(1024) @@ -192,7 +187,6 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, res = connection.recv(10) last_response_contained_ok = "OK" in res.decode() except Exception as e: - sys.stderr.write("\n") logging.error("Error Uploading: %s", str(e)) connection.close() return 1 @@ -202,7 +196,6 @@ def serve(remote_addr, local_addr, remote_port, local_port, password, filename, connection.close() return 0 - sys.stderr.write("\n") logging.info("Waiting for result...") count = 0 while count < 5: diff --git a/app/fw_updater.py b/app/fw_updater.py index 1ca37af..ec19d88 100644 --- a/app/fw_updater.py +++ b/app/fw_updater.py @@ -12,8 +12,9 @@ class FwUpdater: update_progress = None currentlyUpdating = False - def __init__(self, update_progress): + def __init__(self, update_progress, event_cb): self.update_progress = update_progress + self.event_cb = event_cb def get_serial_ports(self): ports = serial.tools.list_ports.comports() @@ -76,6 +77,9 @@ class FwUpdater: self.updatingName = address self.currentlyUpdating = True + + if self.event_cb is not None: + self.event_cb("Starting Firmware update") if os.path.exists(os.path.abspath(local_filename)): thread = Thread(target=self.run_fs_update, args=( @@ -88,6 +92,9 @@ class FwUpdater: self.updatingName = address self.currentlyUpdating = True + + if self.event_cb is not None: + self.event_cb("Starting WebUI update") if os.path.exists(os.path.abspath(local_filename)): thread = Thread(target=self.run_fs_update, args=( diff --git a/app/main.py b/app/main.py index 3c0c173..2b79b05 100644 --- a/app/main.py +++ b/app/main.py @@ -1,9 +1,11 @@ import concurrent.futures +import logging import serial from app.gui.action_button_panel import ActionButtonPanel from app.release_checker import ReleaseChecker import wx +import wx.richtext as rt from zeroconf import ServiceBrowser, Zeroconf import os @@ -18,6 +20,19 @@ from app.zeroconf_listener import ZeroconfListener from app.espota import FLASH, SPIFFS +class RichTextCtrlHandler(logging.Handler): + def __init__(self, ctrl): + super().__init__() + self.ctrl = ctrl + + def emit(self, record): + msg = self.format(record) + wx.CallAfter(self.append_text, msg + '\n') + + def append_text(self, text): + self.ctrl.AppendText(text) + self.ctrl.ShowPosition(self.ctrl.GetLastPosition()) + class SerialPortsComboBox(wx.ComboBox): def __init__(self, parent, fw_update): self.fw_update = fw_update @@ -38,13 +53,23 @@ class BTClockOTAUpdater(wx.Frame): self.browser = ServiceBrowser( self.zeroconf, "_http._tcp.local.", self.listener) self.api_handler = ApiHandler() - self.fw_updater = FwUpdater(self.call_progress) + self.fw_updater = FwUpdater(self.call_progress, self.SetStatusText) + panel = wx.Panel(self) + self.log_ctrl = rt.RichTextCtrl(panel, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2) + monospace_font = wx.Font(10, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) + self.log_ctrl.SetFont(monospace_font) + + handler = RichTextCtrlHandler(self.log_ctrl) + handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) + logging.getLogger().addHandler(handler) + logging.getLogger().setLevel(logging.DEBUG) + + self.device_list = DevicesPanel(panel) vbox = wx.BoxSizer(wx.VERTICAL) - vbox.Add(self.device_list, proportion=2, flag=wx.EXPAND | wx.ALL, border=20) hbox = wx.BoxSizer(wx.HORIZONTAL) @@ -62,10 +87,11 @@ class BTClockOTAUpdater(wx.Frame): self.progress_bar = wx.Gauge(panel, range=100) vbox.Add(self.progress_bar, 0, wx.EXPAND | wx.ALL, 20) + vbox.Add(self.log_ctrl, 1, flag=wx.EXPAND | wx.ALL, border=20) panel.SetSizer(vbox) - self.setup_ui() + wx.CallAfter(self.fetch_latest_release_async) def setup_ui(self): diff --git a/app/release_checker.py b/app/release_checker.py index dcc2d66..c10e04b 100644 --- a/app/release_checker.py +++ b/app/release_checker.py @@ -1,4 +1,5 @@ import json +import logging import os import requests import wx @@ -104,13 +105,14 @@ class ReleaseChecker: def download_file(self, url, release_name): '''Downloads Fimware Files''' local_filename = f"{release_name}_{url.split('/')[-1]}" - response = requests.get(url, stream=True) - total_length = response.headers.get('content-length') + if not os.path.exists("firmware"): os.makedirs("firmware") if os.path.exists(f"firmware/{local_filename}"): return + response = requests.get(url, stream=True) + total_length = response.headers.get('content-length') keep_latest_versions('firmware', 2) if total_length is None: