# SPDX-License-Identifier: GPL-2.0-or-later import datetime import struct import time import threading from PyQt5.QtCore import pyqtSignal from PyQt5.QtGui import QFontDatabase from PyQt5.QtWidgets import QHBoxLayout, QLineEdit, QToolButton, QPlainTextEdit, QProgressBar,QFileDialog, QDialog from basic_editor import BasicEditor from util import tr, chunks from vial_device import VialBootloader def send_retries(dev, data, retries=20): """ Sends usb packet up to 'retries' times, returns True if success, False if failed """ for x in range(retries): ret = dev.send(data) if ret == len(data) + 1: return True elif ret < 0: time.sleep(0.1) else: return False return False CHUNK = 64 def cmd_flash(device, firmware, log_cb, progress_cb, complete_cb, error_cb): while len(firmware) % CHUNK != 0: firmware += b"\x00" # Check bootloader is correct version device.send(b"VC\x00") data = device.recv(8) log_cb("* Bootloader version: {}".format(data[0])) if data[0] != 0: return error_cb("Error: Unsupported bootloader version") # TODO: Check vial ID against firmware package device.send(b"VC\x01") data = device.recv(8) log_cb("* Vial ID: {}".format(data.hex())) # Flash log_cb("Flashing...") device.send(b"VC\x02" + struct.pack(" 10 * 1024 * 1024: self.log("Error: Firmware is too large. Check you've selected the correct file") return self.log("Preparing to flash...") self.lock_ui() threading.Thread(target=lambda: cmd_flash( self.device, firmware, self.on_log, self.on_progress, self.on_complete, self.on_error)).start() def on_log(self, line): self.log_signal.emit(line) def on_progress(self, progress): self.progress_signal.emit(progress) def on_complete(self, msg): self.complete_signal.emit(msg) def on_error(self, msg): self.error_signal.emit(msg) def _on_log(self, msg): self.log(msg) def _on_progress(self, progress): self.progress_bar.setValue(int(progress * 100)) def _on_complete(self, msg): self.log(msg) self.progress_bar.setValue(100) self.unlock_ui() def _on_error(self, msg): self.log(msg) self.unlock_ui() def log(self, line): self.txt_logger.appendPlainText("[{}] {}".format(datetime.datetime.now(), line)) def lock_ui(self): self.btn_select_file.setEnabled(False) self.btn_flash.setEnabled(False) self.main.lock_ui() def unlock_ui(self): self.btn_select_file.setEnabled(True) self.btn_flash.setEnabled(True) self.main.unlock_ui()