Example #1
0
 def __init__(self, callback: UpdaterEvents):
     self.model = ConnectedDeviceModel(
         self)  # the device model using this instance as the view
     # we pass in the proxy because the device model runs on a separate thread, but we want updates to fire on the main controller thread.
     self.callback = callback
     self.scan_thread = None
     self.updater_state = UpdaterState()
     self.updater_state.on_change += lambda source: self._updater_state_changed(
         self.updater_state.state)
     self.updater_state.on_change += lambda source: callback.updater_state_changed(
         self.updater_state.state)
     self.updater_state.notify()  # trigger initial update
Example #2
0
class UpdaterController:
    def __init__(self, callback: UpdaterEvents):
        self.model = ConnectedDeviceModel(
            self)  # the device model using this instance as the view
        # we pass in the proxy because the device model runs on a separate thread, but we want updates to fire on the main controller thread.
        self.callback = callback
        self.scan_thread = None
        self.updater_state = UpdaterState()
        self.updater_state.on_change += lambda source: self._updater_state_changed(
            self.updater_state.state)
        self.updater_state.on_change += lambda source: callback.updater_state_changed(
            self.updater_state.state)
        self.updater_state.notify()  # trigger initial update

    def _set_thread_proxy(self, proxy):
        # rather than using self to handle updates, use the proxy so updates are processed on the controller thraed rather than
        # the background scanner thread
        self.model.view = proxy

    def _updater_state_changed(self, state):
        if state not in [FlashState.in_progress, FlashState.error]:
            self.start_scan(0.25)
        else:
            self.stop_scan()

    def update(self, device):
        self.callback.connected_device_changed(device)
        self.updater_state.set_state(
            FlashState.not_started if device else FlashState.not_connected)

    def scan(self):
        self.model.update()

    def flash(self, connected):
        try:
            self.updater_state.set_state(FlashState.in_progress)
            if connected is None:
                raise ValueError("No device connected")
            connection = USBDeviceConnection(*connected)
            progress = ProgressSpan()

            def progress_update(current):
                self.callback.progress(progress.min, progress.max,
                                       progress.current)

            progress.on_change += progress_update
            Updater().start(progress, connection, connection.device)
            self.updater_state.set_state(FlashState.complete)
        except:
            self.updater_state.set_state(FlashState.error)
            raise

    def start_scan(self, period):
        self.stop_scan()
        event = Event()
        scan_thread = Thread(name="usb scan",
                             target=self._background_scan,
                             args=[period, event],
                             daemon=True)
        scan_thread.event = event
        self.scan_thread = scan_thread
        scan_thread.start()

    def stop_scan(self):
        t = self.scan_thread
        if t:
            t.event.set()
            t.join()

    def _background_scan(self, period, stop_event: Event):
        while not stop_event.is_set():
            self.scan()
            stop_event.wait(period)
        self.scan_thread = None