Skip to content

Commit

Permalink
Improve buttons, use application data dir for cache and downloads
Browse files Browse the repository at this point in the history
  • Loading branch information
dsbaars committed Jun 10, 2024
1 parent 504199a commit 018b043
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 24 deletions.
11 changes: 6 additions & 5 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import wx

from app.main import BTClockOTAUpdater
import wx

app = wx.App(False)
frame = BTClockOTAUpdater(None, 'BTClock OTA updater')
app.MainLoop()
if __name__ == "__main__":
app = wx.App(False)
frame = BTClockOTAUpdater(None, 'BTClock OTA updater')

app.MainLoop()
6 changes: 4 additions & 2 deletions app/fw_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import serial
import wx

from app.utils import get_app_data_folder


class FwUpdater:
update_progress = None
Expand Down Expand Up @@ -72,7 +74,7 @@ def start_firmware_update(self, release_name, address, hw_rev):
if (hw_rev == "REV_B_EPD_2_13"):
model_name = "btclock_rev_b_213epd"

local_filename = f"firmware/{
local_filename = f"{get_app_data_folder()}/{
release_name}_{model_name}_firmware.bin"

self.updatingName = address
Expand All @@ -88,7 +90,7 @@ def start_firmware_update(self, release_name, address, hw_rev):

def start_fs_update(self, release_name, address):
# Path to the firmware file
local_filename = f"firmware/{release_name}_littlefs.bin"
local_filename = f"{get_app_data_folder()}/{release_name}_littlefs.bin"

self.updatingName = address
self.currentlyUpdating = True
Expand Down
2 changes: 1 addition & 1 deletion app/gui/action_button_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def InitUI(self):

self.update_button = wx.Button(self, label="Update Firmware")
self.update_button.Bind(wx.EVT_BUTTON, self.on_click_update_firmware)
self.update_fs_button = wx.Button(self, label="Update Filesystem")
self.update_fs_button = wx.Button(self, label="Update WebUI")
self.update_fs_button.Bind(wx.EVT_BUTTON, self.on_click_update_fs)

self.identify_button = wx.Button(self, label="Identify")
Expand Down
27 changes: 21 additions & 6 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import concurrent.futures
import logging
import traceback

import serial
from app.gui.action_button_panel import ActionButtonPanel
Expand All @@ -15,19 +16,22 @@
from app.api import ApiHandler
from app.fw_updater import FwUpdater
from app.gui.devices_panel import DevicesPanel
from app.utils import get_app_data_folder
from app.zeroconf_listener import ZeroconfListener

from app.espota import FLASH, SPIFFS


class BTClockOTAApp(wx.App):
def OnInit(self):
return True
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')
wx.CallAfter(self.append_text, "\n" + msg)

def append_text(self, text):
self.ctrl.AppendText(text)
Expand All @@ -46,6 +50,7 @@ class BTClockOTAUpdater(wx.Frame):

def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(800, 500))

self.SetMinSize((800, 500))
self.releaseChecker = ReleaseChecker()
self.zeroconf = Zeroconf()
Expand All @@ -62,7 +67,7 @@ def __init__(self, parent, title):
self.log_ctrl.SetFont(monospace_font)

handler = RichTextCtrlHandler(self.log_ctrl)
handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', '%H:%M:%S'))
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.DEBUG)

Expand Down Expand Up @@ -93,7 +98,7 @@ def __init__(self, parent, title):
self.setup_ui()

wx.CallAfter(self.fetch_latest_release_async)

wx.YieldIfNeeded()
def setup_ui(self):
self.setup_menubar()
self.status_bar = self.CreateStatusBar(2)
Expand All @@ -102,15 +107,18 @@ def setup_ui(self):

def setup_menubar(self):
filemenu = wx.Menu()
menuOpenDownloadDir = filemenu.Append(
wx.ID_OPEN, "&Open Download Dir", " Open the directory with firmware files and cache")
menuAbout = filemenu.Append(
wx.ID_ABOUT, "&About", " Information about this program")
menuExit = filemenu.Append(
wx.ID_EXIT, "E&xit", " Terminate the program")

menuBar = wx.MenuBar()
menuBar.Append(filemenu, "&File")
self.SetMenuBar(menuBar)

self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.OnOpenDownloadFolder, menuOpenDownloadDir)
self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
self.Bind(wx.EVT_MENU, self.OnExit, menuExit)

Expand Down Expand Up @@ -175,6 +183,9 @@ def update_progress(self, progress):

def fetch_latest_release_async(self):
# Start a new thread to execute fetch_latest_release
app_folder = get_app_data_folder()
if not os.path.exists(app_folder):
os.makedirs(app_folder)
executor = concurrent.futures.ThreadPoolExecutor()
future = executor.submit(self.releaseChecker.fetch_latest_release)
future.add_done_callback(self.handle_latest_release)
Expand All @@ -186,7 +197,11 @@ def handle_latest_release(self, future):
latest_release}\nCommit: {self.releaseChecker.commit_hash}")
except Exception as e:
self.fw_label.SetLabel(f"Error occurred: {str(e)}")

traceback.print_tb(e.__traceback__)

def OnOpenDownloadFolder(self, e):
wx.LaunchDefaultBrowser(get_app_data_folder())

def OnAbout(self, e):
dlg = wx.MessageDialog(
self, "An updater for BTClocks", "About BTClock OTA Updater", wx.OK)
Expand Down
14 changes: 5 additions & 9 deletions app/release_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
from typing import Callable
from datetime import datetime, timedelta

from app.utils import keep_latest_versions
from app.utils import get_app_data_folder, keep_latest_versions

CACHE_FILE = 'firmware/cache.json'
CACHE_FILE = get_app_data_folder() + '/cache.json'
CACHE_DURATION = timedelta(minutes=30)


Expand Down Expand Up @@ -38,8 +38,6 @@ def fetch_latest_release(self):
cache = self.load_cache()
now = datetime.now()

if not os.path.exists("firmware"):
os.makedirs("firmware")

if 'latest_release' in cache and (now - datetime.fromisoformat(cache['latest_release']['timestamp'])) < CACHE_DURATION:
latest_release = cache['latest_release']['data']
Expand Down Expand Up @@ -106,22 +104,20 @@ def download_file(self, url, release_name):
'''Downloads Fimware Files'''
local_filename = f"{release_name}_{url.split('/')[-1]}"

if not os.path.exists("firmware"):
os.makedirs("firmware")
if os.path.exists(f"firmware/{local_filename}"):
if os.path.exists(f"{get_app_data_folder()}/{local_filename}"):
return

response = requests.get(url, stream=True)
total_length = response.headers.get('content-length')
keep_latest_versions('firmware', 2)
keep_latest_versions(get_app_data_folder(), 2)

if total_length is None:
raise ReleaseCheckerException("No content length header")
else:
total_length = int(total_length)
chunk_size = 1024
num_chunks = total_length // chunk_size
with open(f"firmware/{local_filename}", 'wb') as f:
with open(f"{get_app_data_folder()}/{local_filename}", 'wb') as f:
for i, chunk in enumerate(response.iter_content(chunk_size=chunk_size)):
if chunk:
f.write(chunk)
Expand Down
15 changes: 14 additions & 1 deletion app/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
import re
import shutil
import wx


def count_versions(folder_path):
Expand Down Expand Up @@ -30,3 +30,16 @@ def keep_latest_versions(folder_path, num_versions_to_keep=2):
for version in versions_to_remove:
for file_name in version_files[version]:
os.remove(os.path.join(folder_path, file_name))

def get_app_data_folder():
app = wx.GetApp()
if app is None:
app = wx.App(False)
standard_paths = wx.StandardPaths.Get()
app_data_dir = standard_paths.GetAppDocumentsDir() + "/BTClockOTA"
app.Destroy()
return app_data_dir
else:
standard_paths = wx.StandardPaths.Get()
app_data_dir = standard_paths.GetAppDocumentsDir() + "/BTClockOTA"
return app_data_dir

0 comments on commit 018b043

Please sign in to comment.