async def _do_connect(self): _logger.info("Connection initialization task spawned") try: selected_port = self._port_mapping[str( self._port_combo.currentText()).strip()] except KeyError: selected_port = str(self._port_combo.currentText()).strip() # Activate the progress view and initialize it self._overlay.setCurrentIndex(1) self._connection_progress_bar.setValue(0) self._connection_progress_bar.setFormat("Requesting connection...") # noinspection PyBroadException try: device_info: BasicDeviceInfo = await self._connection_request_callback( selected_port) except Exception as ex: show_error( "Could not connect", f"Connection via the port {selected_port} could not be established.", f"Reason: {str(ex)}", parent=self, ) self._switch_state_disconnected() else: assert device_info is not None self._switch_state_connected(device_info)
def show_error_box(result: CheckResult, detail: str, file_name: str, parent: WidgetBase): show_error( "Import failed", f"Cannot import {file_name}", CHECK_RESULT_MAPPING[result] + detail, parent, )
def import_registers(parent: WidgetBase, registers: list): """ Imports registers values from a .yml (or .yaml) file. The file must match the following pattern: full_register_name: - register_value e.g: ctl.num_attempts: - 100 ctl.pwron_slftst: - false ctl.spinup_durat: - 1.7000000476837158 It can only contain available registers on the current device, with values within the allowed range. The values must be the right type and dimension. If a register is not mentioned in the file, it will keep its former value. """ dialog_box = QWidget() dialog_box.setGeometry(10, 10, 1000, 700) file_name, _ = QFileDialog.getOpenFileName( dialog_box, "Import configuration file", "", "YAML Files (*.yml *.yaml);;All Files (*)", ) if not file_name: return try: with open(file_name, "r") as file: imported_registers = yaml.load(file, Loader=yaml.Loader) except IOError as ex: _logger.exception(f"File {file_name} could not be open") show_error("Import failed", f"Cannot open {file_name}", f"Error: {str(ex)}", parent) return except Exception as ex: _logger.exception(f"File {file_name} could not be parsed") show_error("Import failed", f"Cannot read {file_name}", f"Error: {str(ex)}", parent) return if imported_registers: result, detail = check_registers(registers, imported_registers) if result == CheckResult.NO_ERROR: write_registers(parent, file_name, registers, imported_registers) else: show_error_box(result, detail, file_name, parent)
async def executor(): try: _logger.info('Writing registers: %r', [r.name for r in register_value_mapping.keys()]) mod: Model = self._tree.model() await mod.write(register_value_mapping=register_value_mapping, progress_callback=progress_callback) except asyncio.CancelledError: self._display_status(f'Write has been cancelled') raise except Exception as ex: _logger.exception('Register write failed') show_error('Write failed', 'Could not read registers', repr(ex), self) self._display_status(f'Could not write registers: {ex!r}') else: self._display_status(f'{total_registers_assigned} registers have been written')
async def executor(): try: _logger.info('Reading registers: %r', [r.name for r in registers]) mod: Model = self._tree.model() await mod.read(registers=registers, progress_callback=progress_callback) except asyncio.CancelledError: self._display_status(f'Read has been cancelled') raise except Exception as ex: _logger.exception('Register read failed') show_error('Read failed', 'Could not read registers', repr(ex), self) self._display_status(f'Could not read registers: {ex!r}') else: self._display_status(f'{total_registers_read} registers have been read')
def _on_confirmation(self): # Deactivate the controls in order to prevent accidental double-entry self._port_combo.setEnabled(False) self._connect_button.setEnabled(False) if (self._last_task is not None) and not self._last_task.done(): show_error( "I'm sorry Dave, I'm afraid I can't do that", 'Cannot connect/disconnect while another connection/disconnection operation is still running', f'Pending future: {self._last_task}', self) else: if not self._connection_established: self._last_task = asyncio.get_event_loop().create_task( self._do_connect()) else: self._last_task = asyncio.get_event_loop().create_task( self._do_disconnect())
async def executor(): try: register_yaml = {} for reg in registers: if reg.mutable and reg.persistent: register_yaml[reg.name] = await reg.read_through() yaml.dump(register_yaml, _file) display_sucess_message( 'Export successful', f'Parameters have been successfully exported to:\n{file_name}', parent) except Exception as ex: show_error('Export failed', f'Parameters cannot be read.', str(ex), parent) _logger.exception(f'Registers could not be read') finally: _file.close()
def export_registers(parent: WidgetBase, registers: list): """ Stores all mutable and persistent registers in a .yml file. """ dialog_box = QWidget() dialog_box.setGeometry(10, 10, 1000, 700) file_name, _ = QFileDialog.getSaveFileName( dialog_box, "Export configuration file", "config.yml", "YAML Files (*.yml *.yaml);;All Files (*)", ) if not file_name: return try: _file = open(file_name, "w+") except Exception as ex: show_error("Export failed", f"Cannot open {file_name}", f"Error: {str(ex)}", parent) _logger.exception(f"File {file_name} could not be open: {str(ex)}") return async def executor(): try: register_yaml = {} for reg in registers: if reg.mutable and reg.persistent: register_yaml[reg.name] = await reg.read_through() yaml.dump(register_yaml, _file) display_sucess_message( "Export successful", f"Parameters have been successfully exported to:\n{file_name}", parent, ) except Exception as ex: show_error("Export failed", f"Parameters cannot be read.", str(ex), parent) _logger.exception(f"Registers could not be read") finally: _file.close() asyncio.get_event_loop().create_task(executor())
def setModelData(self, editor: QWidget, model: QAbstractItemModel, index: QModelIndex): """Invoked ad the end of the editing session; data transferred from the editor to the model""" register = self._get_register_from_index(index) if isinstance(editor, QComboBox): assert self._can_use_bool_switch(register) # >>> int('1') # 1 # >>> bool(int(False)) # False # >>> bool('False') # True # Wait what?! value = bool(editor.currentIndex()) _logger.info("Value %r has been interpreted as %r", editor.currentText(), value) elif isinstance(editor, (QDoubleSpinBox, QSpinBox)): assert self._can_use_spinbox(register) editor.interpretText() # Beware!!1 value = editor.value() elif isinstance(editor, QPlainTextEdit): assert not self._can_use_spinbox(register) text = editor.toPlainText() try: value = parse_value(text, register.type_id) except Exception as ex: _logger.warning("The following value could not be parsed: %r", text, exc_info=True) show_error( "Invalid value", "Could not parse the entered value", repr(ex), editor.window(), ) value = None else: raise TypeError(f"Unexpected editor: {editor}") # We're not going to touch the device here; instead, we're going to delegate that back to the Model instance. if value is not None: model.setData(index, value, Qt.EditRole)