Exemple #1
0
    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)
Exemple #2
0
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,
    )
Exemple #3
0
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)
Exemple #4
0
 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')
Exemple #5
0
 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')
Exemple #6
0
    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()
Exemple #8
0
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())
Exemple #9
0
    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)