Skip to content

Commit

Permalink
Quickdeploy (#18)
Browse files Browse the repository at this point in the history
* improve configuration handling

* change config variable names to snake case

* populate tag ui with github api

* tag box and asset box update each other

* only call api once

* fix some combo box formatting

* clean up combobox callbacks

* working cancel button with quick mode

* get download url by tag and name

* working somewhat

* all modes working
  • Loading branch information
Alex R authored Apr 13, 2021
1 parent 77f209d commit 677c37a
Show file tree
Hide file tree
Showing 5 changed files with 331 additions and 61 deletions.
32 changes: 23 additions & 9 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,42 @@ def __init__(self):
self.manager = None
config = self.configuration_setup()
self.mode = config["settings"]["mode"]
self.deploy_type = config["settings"]["deploy_type"]
super().__init__(
application_id="org.gnome.siglo", flags=Gio.ApplicationFlags.FLAGS_NONE
)

def configuration_setup(self):
config = configparser.ConfigParser()
home = str(Path.home())
configDir = home + "/.config/siglo"
if not Path(configDir).is_dir():
Path.mkdir(Path(configDir))
configFile = configDir + "/siglo.ini"
if not Path(configFile).is_file():
config["settings"] = {"mode": "singleton"}
with open(configFile, "w") as f:
config_dir = home + "/.config/siglo"
if not Path(config_dir).is_dir():
Path.mkdir(Path(config_dir))
config_file = config_dir + "/siglo.ini"
if not self.config_file_is_valid(config, config_file):
config["settings"] = {"mode": "singleton", "deploy_type": "quick"}
with open(config_file, "w") as f:
config.write(f)
config.read(configFile)
config.read(config_file)
return config

def config_file_is_valid(self, config, config_file):
keys = ("mode", "deploy_type")
if not Path(config_file).is_file():
return False
else:
config.read(config_file)
for key in keys:
if not key in config["settings"]:
return False
return True

def do_activate(self):
win = self.props.active_window
if not win:
win = SigloWindow(application=self, mode=self.mode)
win = SigloWindow(
application=self, mode=self.mode, deploy_type=self.deploy_type
)
win.present()
self.manager = InfiniTimeManager(self.mode)
info_prefix = "[INFO ] Done Scanning"
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ configure_file(

siglo_sources = [
'__init__.py',
'quick_deploy.py',
'main.py',
'window.py',
'bluetooth.py',
Expand Down
56 changes: 56 additions & 0 deletions src/quick_deploy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import requests
import json

url = "https://api.github.com/repos/JF002/InfiniTime/releases"
version_blacklist = (
"0.6.0",
"0.6.1",
"0.6.2",
"0.7.0",
"0.7.1",
"0.8.0-develop",
"0.8.1-develop",
"0.8.2-develop",
"0.9.0-develop",
"0.9.0",
"0.8.3",
"0.8.2"
)


def get_quick_deploy_list():
r = requests.get(url)
d = json.loads(r.content)
quick_deploy_list = []
for item in d:
for asset in item["assets"]:
if (
asset["content_type"] == "application/zip"
and item["tag_name"] not in version_blacklist
):
helper_dict = {
"tag_name": item["tag_name"],
"name": asset["name"],
"browser_download_url": asset["browser_download_url"],
}
quick_deploy_list.append(helper_dict)
return quick_deploy_list


def get_tags(full_list):
tags = set()
for element in full_list:
tags.add(element["tag_name"])
return sorted(tags, reverse=True)

def get_assets_by_tag(tag, full_list):
asset_list = []
for element in full_list:
if tag == element["tag_name"]:
asset_list.append(element["name"])
return asset_list

def get_download_url(name, tag, full_list):
for element in full_list:
if tag == element["tag_name"] and name == element["name"]:
return element["browser_download_url"]
148 changes: 122 additions & 26 deletions src/window.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import threading
import gatt
import configparser
import urllib.request
from pathlib import Path
from gi.repository import Gtk, GObject
from .bluetooth import InfiniTimeDevice
from .ble_dfu import InfiniTimeDFU
from .unpacker import Unpacker
from .quick_deploy import *


@Gtk.Template(resource_path="/org/gnome/siglo/window.ui")
Expand All @@ -25,17 +26,32 @@ class SigloWindow(Gtk.ApplicationWindow):
multi_device_listbox = Gtk.Template.Child()
rescan_button = Gtk.Template.Child()
multi_device_switch = Gtk.Template.Child()
auto_bbox_scan_pass = Gtk.Template.Child()
bbox_scan_pass = Gtk.Template.Child()
ota_pick_tag_combobox = Gtk.Template.Child()
ota_pick_asset_combobox = Gtk.Template.Child()
ota_pick_asset_combobox = Gtk.Template.Child()
deploy_type_switch = Gtk.Template.Child()

def __init__(self, mode, **kwargs):
def __init__(self, mode, deploy_type, **kwargs):
self.ble_dfu = None
self.ota_file = None
self.manager = None
self.asset = None
self.asset_download_url = None
self.tag = None
self.mode = mode
self.deploy_type = deploy_type
super().__init__(**kwargs)
GObject.threads_init()
if mode == "multi":
self.auto_switch = True
self.auto_switch_mode = True
self.multi_device_switch.set_active(True)
if deploy_type == "quick":
self.full_list = get_quick_deploy_list()
if deploy_type == "manual":
self.auto_switch_deploy_type = True
self.deploy_type_switch.set_active(True)

def depopulate_listbox(self):
children = self.multi_device_listbox.get_children()
Expand All @@ -59,6 +75,15 @@ def populate_listbox(self):
self.multi_device_listbox.set_visible(True)
self.multi_device_listbox.show_all()

def populate_tagbox(self):
for tag in get_tags(self.full_list):
self.ota_pick_tag_combobox.append_text(tag)

def populate_assetbox(self):
self.ota_pick_asset_combobox.remove_all()
for asset in get_assets_by_tag(self.tag, self.full_list):
self.ota_pick_asset_combobox.append_text(asset)

def done_scanning_multi(self, manager, info_prefix):
self.manager = manager
scan_result = manager.get_scan_result()
Expand Down Expand Up @@ -88,12 +113,57 @@ def done_scanning_singleton(self, manager, info_prefix):
+ manager.get_mac_address()
)
self.scan_pass_box.set_visible(True)
self.ota_picked_box.set_visible(True)
if self.deploy_type == "quick":
self.auto_bbox_scan_pass.set_visible(True)
self.populate_tagbox()
if self.deploy_type == "manual":
self.bbox_scan_pass.set_visible(True)
else:
info_suffix += "\n[INFO ] Scan Failed"
self.rescan_button.set_visible(True)
self.scan_fail_box.set_visible(True)
self.main_info.set_text(info_prefix + info_suffix)

@Gtk.Template.Callback()
def multi_listbox_row_selected(self, list_box, row):
if row is not None:
mac_add = row.get_child().get_label()
self.manager.set_mac_address(mac_add)
self.info_scan_pass.set_text(
self.manager.alias
+ " Found!\n\nAdapter Name: "
+ self.manager.adapter_name
+ "\nMac Address: "
+ self.manager.get_mac_address()
)
print("deploy type!", self.deploy_type)
self.scan_pass_box.set_visible(True)
self.ota_picked_box.set_visible(True)
if self.deploy_type == "manual":
self.bbox_scan_pass.set_visible(True)
if self.deploy_type == "quick":
self.auto_bbox_scan_pass.set_visible(True)
self.populate_tagbox()
self.multi_device_listbox.set_visible(False)

@Gtk.Template.Callback()
def ota_pick_tag_combobox_changed_cb(self, widget):
self.tag = self.ota_pick_tag_combobox.get_active_text()
self.populate_assetbox()

@Gtk.Template.Callback()
def ota_pick_asset_combobox_changed_cb(self, widget):
self.asset = self.ota_pick_asset_combobox.get_active_text()
if self.asset is not None:
self.ota_picked_box.set_sensitive(True)
self.asset_download_url = get_download_url(
self.asset, self.tag, self.full_list
)
else:
self.ota_picked_box.set_sensitive(False)
self.asset_download_url = None

@Gtk.Template.Callback()
def rescan_button_clicked(self, widget):
if self.manager is not None:
Expand Down Expand Up @@ -133,19 +203,34 @@ def ota_file_selected(self, widget):
self.main_info.set_text("File: " + filename.split("/")[-1])
self.ota_picked_box.set_visible(True)
self.ota_selection_box.set_visible(False)
self.ota_picked_box.set_sensitive(True)

@Gtk.Template.Callback()
def ota_cancel_button_clicked(self, widget):
self.main_info.set_text("Choose another OTA File")
self.ota_picked_box.set_visible(False)
self.ota_selection_box.set_visible(True)
if self.deploy_type == "quick":
self.ota_pick_asset_combobox.remove_all()
self.ota_pick_tag_combobox.remove_all()
self.populate_tagbox()
self.ota_picked_box.set_sensitive(False)
if self.deploy_type == "manual":
self.main_info.set_text("Choose another OTA File")
self.ota_picked_box.set_visible(False)
self.ota_selection_box.set_visible(True)

@Gtk.Template.Callback()
def flash_it_button_clicked(self, widget):
if self.deploy_type == "quick":
file_name = "/tmp/" + self.asset
local_filename, headers = urllib.request.urlretrieve(
self.asset_download_url, file_name
)
self.ota_file = local_filename

self.main_info.set_text("Updating Firmware...")
self.ota_picked_box.set_visible(False)
self.dfu_progress_box.set_visible(True)
self.sync_time_button.set_visible(False)
self.auto_bbox_scan_pass.set_visible(False)
unpacker = Unpacker()
try:
binfile, datfile = unpacker.unpack_zipfile(self.ota_file)
Expand All @@ -165,21 +250,46 @@ def flash_it_button_clicked(self, widget):
self.dfu_progress_text.set_text(self.get_prog_text())
self.ble_dfu.connect()

@Gtk.Template.Callback()
def deploy_type_toggled(self, widget):
if self.deploy_type == "manual" and self.auto_switch_deploy_type:
self.auto_switch_deploy_type = False
else:
current_deploy_type = self.deploy_type
config = configparser.ConfigParser()
home = str(Path.home())
configDir = home + "/.config/siglo"
configFile = configDir + "/siglo.ini"
if current_deploy_type == "quick":
config["settings"] = {"mode": self.mode, "deploy_type": "manual"}
self.deploy_type = "manual"
if current_deploy_type == "manual":
config["settings"] = {"mode": self.mode, "deploy_type": "quick"}
self.deploy_type = "quick"
with open(configFile, "w") as f:
config.write(f)
self.main_info.set_text("[WARN ] Settings changed, please restart Siglo")
self.rescan_button.set_visible(False)
self.scan_pass_box.set_visible(False)
self.depopulate_listbox()
self.scan_fail_box.set_visible(False)
self.auto_bbox_scan_pass.set_visible(False)

@Gtk.Template.Callback()
def mode_toggled(self, widget):
if self.mode == "multi" and self.auto_switch == True:
self.auto_switch = False
if self.mode == "multi" and self.auto_switch_mode == True:
self.auto_switch_mode = False
else:
current_mode = self.mode
config = configparser.ConfigParser()
home = str(Path.home())
configDir = home + "/.config/siglo"
configFile = configDir + "/siglo.ini"
if current_mode == "singleton":
config["settings"] = {"mode": "multi"}
config["settings"] = {"mode": "multi", "deploy_type": self.deploy_type}
self.mode = "multi"
if current_mode == "multi":
config["settings"] = {"mode": "singleton"}
config["settings"] = {"mode": "singleton", "deploy_type": self.deploy_type}
self.mode = "singleton"
with open(configFile, "w") as f:
config.write(f)
Expand All @@ -189,22 +299,6 @@ def mode_toggled(self, widget):
self.depopulate_listbox()
self.scan_fail_box.set_visible(False)

@Gtk.Template.Callback()
def multi_listbox_row_selected(self, list_box, row):
if row is not None:
mac_add = row.get_child().get_label()
self.manager.set_mac_address(mac_add)
self.info_scan_pass.set_text(
self.manager.alias
+ " Found!\n\nAdapter Name: "
+ self.manager.adapter_name
+ "\nMac Address: "
+ self.manager.get_mac_address()
)
self.scan_pass_box.set_visible(True)
self.multi_device_listbox.set_visible(False)


def update_progress_bar(self):
self.dfu_progress_bar.set_fraction(
self.ble_dfu.total_receipt_size / self.ble_dfu.image_size
Expand All @@ -224,3 +318,5 @@ def show_complete(self):
self.bt_spinner.set_visible(False)
self.sync_time_button.set_visible(True)
self.dfu_progress_box.set_visible(False)
if (self.deploy_type == "quick"):
self.auto_bbox_scan_pass.set_visible(True)
Loading

0 comments on commit 677c37a

Please sign in to comment.