Example #1
0
 def log_all_params():
     for index in range(10000):
         r = request(uavcan.protocol.param.GetSet.Request(index=index))
         if not r.name:
             break
         logger.info('Param %-30r %r' % (r.name.decode(),
                                         getattr(r.value, uavcan.get_active_union_field(r.value))))
        def handle_param_write(self, req):
            request = uavcan.protocol.param.GetSet.Request(
                name=req.name,
                value=uavcan.protocol.param.Value(
                    integer_value=req.value
                ),
            )
            _uav_outgoing.put(request)
            try:
                response = _uav_incoming_param.get(
                    block=True,
                    timeout=PARAMETER_REQ_TIMEOUT,
                )
                if (
                    uavcan.get_active_union_field(
                        response.value
                    )
                    != "empty"
                ):
                    return (
                        SUCCESS
                        if response.value.integer_value
                        == req.value
                        else FAILURE
                    )
            except queue.Empty:
                pass

            return FAILURE
    def __init__(self, parent, node, target_node_id):
        super(ConfigParams, self).__init__(parent)
        self.setTitle('Configuration parameters (double click to change)')

        self._node = node
        self._target_node_id = target_node_id

        self._read_all_button = make_icon_button(
            'refresh',
            'Fetch all config parameters from the node',
            self,
            text='Fetch All',
            on_clicked=self._do_reload)

        opcodes = uavcan.protocol.param.ExecuteOpcode.Request()

        self._save_button = \
            make_icon_button('database', 'Commit configuration to the non-volatile storage [OPCODE_SAVE]', self,
                             text='Store All', on_clicked=partial(self._do_execute_opcode, opcodes.OPCODE_SAVE))

        self._erase_button = \
            make_icon_button('eraser', 'Clear the non-volatile configuration storage [OPCODE_ERASE]', self,
                             text='Erase All', on_clicked=partial(self._do_execute_opcode, opcodes.OPCODE_ERASE))

        columns = [
            BasicTable.Column('Idx', lambda m: m[0]),
            BasicTable.Column('Name',
                              lambda m: m[1].name,
                              resize_mode=QHeaderView.Stretch),
            BasicTable.Column(
                'Type',
                lambda m: uavcan.get_active_union_field(m[1].value).replace(
                    '_value', '')),
            BasicTable.Column('Value',
                              lambda m: render_union(m[1].value),
                              resize_mode=QHeaderView.Stretch),
            BasicTable.Column('Default',
                              lambda m: render_union(m[1].default_value)),
            BasicTable.Column('Min', lambda m: render_union(m[1].min_value)),
            BasicTable.Column('Max', lambda m: render_union(m[1].max_value)),
        ]

        self._table = BasicTable(self,
                                 columns,
                                 multi_line_rows=True,
                                 font=get_monospace_font())
        self._table.cellDoubleClicked.connect(
            lambda row, col: self._do_edit_param(row))
        self._table.on_enter_pressed = self._on_cell_enter_pressed

        self._params = []

        layout = QVBoxLayout(self)
        controls_layout = QHBoxLayout(self)
        controls_layout.addWidget(self._read_all_button, 1)
        controls_layout.addWidget(self._save_button, 1)
        controls_layout.addWidget(self._erase_button, 1)
        layout.addLayout(controls_layout)
        layout.addWidget(self._table)
        self.setLayout(layout)
def _extract_struct_fields(m):
    if isinstance(m, uavcan.transport.CompoundValue):
        out = CompactMessage(uavcan.get_uavcan_data_type(m).full_name)
        for field_name, field in uavcan.get_fields(m).items():
            if uavcan.is_union(
                    m) and uavcan.get_active_union_field(m) != field_name:
                continue
            val = _extract_struct_fields(field)
            if val is not None:
                out._add_field(field_name, val)
        return out
    elif isinstance(m, uavcan.transport.ArrayValue):
        # cannot say I'm breaking the rules
        container = bytes if uavcan.get_uavcan_data_type(
            m).is_string_like else list
        # if I can glue them back together
        return container(
            filter(lambda x: x is not None,
                   (_extract_struct_fields(item) for item in m)))
    elif isinstance(m, uavcan.transport.PrimitiveValue):
        return m.value
    elif isinstance(m, (int, float, bool)):
        return m
    elif isinstance(m, uavcan.transport.VoidValue):
        pass
    else:
        raise ValueError(':(')
Example #5
0
    def _do_send(self):
        value_type = uavcan.get_active_union_field(self._param_struct.value)

        try:
            if value_type == "integer_value":
                if hasattr(self._value_widget, "value"):
                    value = int(self._value_widget.value())
                else:
                    value = int(self._value_widget.text())
                self._param_struct.value.integer_value = value
            elif value_type == "real_value":
                value = float(self._value_widget.text())
                self._param_struct.value.real_value = value
            elif value_type == "boolean_value":
                value = bool(self._value_widget.isChecked())
                self._param_struct.value.boolean_value = value
            elif value_type == "string_value":
                value = self._value_widget.text()
                self._param_struct.value.string_value = value
            else:
                raise RuntimeError("This is not happening!")
        except Exception as ex:
            show_error("Format error", "Could not parse value", ex, self)
            return

        try:
            request = uavcan.protocol.param.GetSet.Request(name=self._param_struct.name, value=self._param_struct.value)
            logger.info("Sending param set request: %s", request)
            self._node.request(request, self._target_node_id, self._on_response, priority=REQUEST_PRIORITY)
        except Exception as ex:
            show_error("Node error", "Could not send param set request", ex, self)
        else:
            self.show_message("Set request sent")
Example #6
0
    def _do_send(self):
        value_type = uavcan.get_active_union_field(self._param_struct.value)

        try:
            if value_type == 'integer_value':
                if hasattr(self._value_widget, 'value'):
                    value = int(self._value_widget.value())
                else:
                    value = int(self._value_widget.text())
                self._param_struct.value.integer_value = value
            elif value_type == 'real_value':
                value = float(self._value_widget.text())
                self._param_struct.value.real_value = value
            elif value_type == 'boolean_value':
                value = bool(self._value_widget.isChecked())
                self._param_struct.value.boolean_value = value
            elif value_type == 'string_value':
                value = self._value_widget.text()
                self._param_struct.value.string_value = value
            else:
                raise RuntimeError('This is not happening!')
        except Exception as ex:
            show_error('Format error', 'Could not parse value', ex, self)
            return

        try:
            request = uavcan.protocol.param.GetSet.Request(name=self._param_struct.name,
                                                           value=self._param_struct.value)
            logger.info('Sending param set request: %s', request)
            self._node.request(request, self._target_node_id, self._on_response, priority=REQUEST_PRIORITY)
        except Exception as ex:
            show_error('Node error', 'Could not send param set request', ex, self)
        else:
            self.show_message('Set request sent')
 def handle_param_list(self, req):
     params = []
     index = 0
     ClearQueue(_uav_incoming_param)
     while True:
         request = uavcan.protocol.param.GetSet.Request(
             index=index
         )
         _uav_outgoing.put(request)
         try:
             response = _uav_incoming_param.get(
                 block=True,
                 timeout=PARAMETER_REQ_TIMEOUT,
             )
             if (
                 uavcan.get_active_union_field(
                     response.value
                 )
                 != "empty"
             ):
                 params.append(
                     ascii_list_to_str(response.name)
                 )
                 index += 1
                 rospy.loginfo(index)
             else:
                 return [SUCCESS, params]
         except queue.Empty:
             return [FAILURE, params]
Example #8
0
def _to_json_compatible_object_impl(obj):
    # Decomposing PrimitiveValue to value and type. This is ugly but it's by design...
    if isinstance(obj, PrimitiveValue):
        obj = obj.value

    # CompoundValue
    if isinstance(obj, CompoundValue):
        output = dict()
        for field_name, field in uavcan.get_fields(obj).items():
            if uavcan.is_union(
                    obj) and uavcan.get_active_union_field(obj) != field_name:
                continue
            if isinstance(field, VoidValue):
                continue

            output[field_name] = to_json_compatible_object(field)
        return output

    # ArrayValue
    elif isinstance(obj, ArrayValue):
        t = uavcan.get_uavcan_data_type(obj)
        if t.value_type.category == t.value_type.CATEGORY_PRIMITIVE:

            def is_nice_character(ch):
                if ch.is_printable() or ch.isspace():
                    return True
                if ch in b'\n\r\t':
                    return True
                return False

            # Catch a string masquerading as an array
            if t.is_string_like and all(map(is_nice_character, obj)):
                return obj.decode()

        # Return the array!
        output = []
        for x in obj:
            output.append(to_json_compatible_object(x))

        return output

    # Primitive types
    elif isinstance(obj, float):
        return obj
    elif isinstance(obj, bool):
        return obj
    elif isinstance(obj, int):
        return obj

    # Non-printable types
    elif isinstance(obj, VoidValue):
        pass

    # Unknown types
    else:
        raise ValueError(
            'Cannot generate JSON-compatible object representation for %r' %
            type(obj))
def render_union(u):
    value = get_union_value(u)
    if 'boolean' in uavcan.get_active_union_field(u):
        return bool(value)
    if isinstance(value, int):
        return value
    if isinstance(value, float):
        return round_float(value)
    if 'uavcan.protocol.param.Empty' in str(value):
        return ''
    return value
Example #10
0
 def log_all_params():
     for index in range(10000):
         r = request(
             uavcan.protocol.param.GetSet.Request(index=index))
         if not r.name:
             break
         logger.info(
             'Param %-30r %r' %
             (r.name.decode(),
              getattr(r.value, uavcan.get_active_union_field(
                  r.value))))
Example #11
0
def render_union(u):
    value = get_union_value(u)
    if "boolean" in uavcan.get_active_union_field(u):
        return bool(value)
    if isinstance(value, int):
        return value
    if isinstance(value, float):
        return round_float(value)
    if "uavcan.protocol.param.Empty" in str(value):
        return ""
    return value
Example #12
0
    def __init__(self, parent, node, target_node_id):
        super(ConfigParams, self).__init__(parent)
        self.setTitle("Configuration parameters (double click to change)")

        self._node = node
        self._target_node_id = target_node_id

        self._read_all_button = make_icon_button(
            "refresh", "Fetch all config parameters from the node", self, text="Fetch All", on_clicked=self._do_reload
        )

        opcodes = uavcan.protocol.param.ExecuteOpcode.Request()

        self._save_button = make_icon_button(
            "database",
            "Commit configuration to the non-volatile storage [OPCODE_SAVE]",
            self,
            text="Store All",
            on_clicked=partial(self._do_execute_opcode, opcodes.OPCODE_SAVE),
        )

        self._erase_button = make_icon_button(
            "eraser",
            "Clear the non-volatile configuration storage [OPCODE_ERASE]",
            self,
            text="Erase All",
            on_clicked=partial(self._do_execute_opcode, opcodes.OPCODE_ERASE),
        )

        columns = [
            BasicTable.Column("Idx", lambda m: m[0]),
            BasicTable.Column("Name", lambda m: m[1].name, resize_mode=QHeaderView.Stretch),
            BasicTable.Column("Type", lambda m: uavcan.get_active_union_field(m[1].value).replace("_value", "")),
            BasicTable.Column("Value", lambda m: render_union(m[1].value), resize_mode=QHeaderView.Stretch),
            BasicTable.Column("Default", lambda m: render_union(m[1].default_value)),
            BasicTable.Column("Min", lambda m: render_union(m[1].min_value)),
            BasicTable.Column("Max", lambda m: render_union(m[1].max_value)),
        ]

        self._table = BasicTable(self, columns, multi_line_rows=True, font=get_monospace_font())
        self._table.cellDoubleClicked.connect(lambda row, col: self._do_edit_param(row))
        self._table.on_enter_pressed = self._on_cell_enter_pressed

        self._params = []

        layout = QVBoxLayout(self)
        controls_layout = QHBoxLayout(self)
        controls_layout.addWidget(self._read_all_button, 1)
        controls_layout.addWidget(self._save_button, 1)
        controls_layout.addWidget(self._erase_button, 1)
        layout.addLayout(controls_layout)
        layout.addWidget(self._table)
        self.setLayout(layout)
Example #13
0
    def _assign(self, value_union):
        value = get_union_value(value_union)

        if uavcan.get_active_union_field(value_union) == "real_value":
            value = round_float(value)

        if hasattr(self._value_widget, "setValue"):
            self._value_widget.setValue(value)
            self._update_callback(value)
        elif hasattr(self._value_widget, "setChecked"):
            self._value_widget.setChecked(bool(value))
            self._update_callback(bool(value))
        else:
            self._value_widget.setText(str(value))
            self._update_callback(value)
    def _assign(self, value_union):
        value = get_union_value(value_union)

        if uavcan.get_active_union_field(value_union) == 'real_value':
            value = round_float(value)

        if hasattr(self._value_widget, 'setValue'):
            self._value_widget.setValue(value)
            self._update_callback(value)
        elif hasattr(self._value_widget, 'setChecked'):
            self._value_widget.setChecked(bool(value))
            self._update_callback(bool(value))
        else:
            self._value_widget.setText(str(value))
            self._update_callback(value)
Example #15
0
 def set_param(name, value, union_field=None):
     union_field = union_field or {
         int: 'integer_value',
         float: 'real_value',
         bool: 'boolean_value',
         str: 'string_value'
     }[type(value)]
     logger.info('Setting parameter %r field %r value %r', name, union_field, value)
     req = uavcan.protocol.param.GetSet.Request()
     req.name.encode(name)
     setattr(req.value, union_field, value)
     r = request(req)
     enforce(uavcan.get_active_union_field(r.value) == union_field,
             'Union field mismatch in param set response for %r', name)
     enforce(getattr(r.value, union_field) == value,
             'The node refused to set parameter %r', name)
Example #16
0
 def set_param(name, value, union_field=None):
     union_field = union_field or {
         int: 'integer_value',
         float: 'real_value',
         bool: 'boolean_value',
         str: 'string_value'
     }[type(value)]
     logger.info('Setting parameter %r field %r value %r', name,
                 union_field, value)
     req = uavcan.protocol.param.GetSet.Request()
     req.name.encode(name)
     setattr(req.value, union_field, value)
     r = request(req)
     enforce(
         uavcan.get_active_union_field(r.value) == union_field,
         'Union field mismatch in param set response for %r', name)
     enforce(
         getattr(r.value, union_field) == value,
         'The node refused to set parameter %r', name)
Example #17
0
def _extract_struct_fields(m):
    if isinstance(m, uavcan.transport.CompoundValue):
        out = CompactMessage(uavcan.get_uavcan_data_type(m).full_name)
        for field_name, field in uavcan.get_fields(m).items():
            if uavcan.is_union(m) and uavcan.get_active_union_field(m) != field_name:
                continue
            val = _extract_struct_fields(field)
            if val is not None:
                out._add_field(field_name, val)
        return out
    elif isinstance(m, uavcan.transport.ArrayValue):
        # cannot say I'm breaking the rules
        container = bytes if uavcan.get_uavcan_data_type(m).is_string_like else list
        # if I can glue them back together
        return container(filter(lambda x: x is not None, (_extract_struct_fields(item) for item in m)))
    elif isinstance(m, uavcan.transport.PrimitiveValue):
        return m.value
    elif isinstance(m, (int, float, bool)):
        return m
    elif isinstance(m, uavcan.transport.VoidValue):
        pass
    else:
        raise ValueError(':(')
Example #18
0
def _to_yaml_impl(obj,
                  indent_level=0,
                  parent=None,
                  name=None,
                  uavcan_type=None):
    buf = StringIO()

    def write(fmt, *args):
        buf.write((fmt % args) if len(args) else fmt)

    def indent_newline():
        buf.write(os.linesep + ' ' * 2 * indent_level)

    # Decomposing PrimitiveValue to value and type. This is ugly but it's by design...
    if isinstance(obj, PrimitiveValue):
        uavcan_type = uavcan.get_uavcan_data_type(obj)
        obj = obj.value

    # CompoundValue
    if isinstance(obj, CompoundValue):
        first_field = True

        # Rendering all fields than can be rendered
        for field_name, field in uavcan.get_fields(obj).items():
            if uavcan.is_union(
                    obj) and uavcan.get_active_union_field(obj) != field_name:
                continue
            if isinstance(field, VoidValue):
                continue
            if (first_field and indent_level > 0) or not first_field:
                indent_newline()
            first_field = False
            rendered_field = _to_yaml_impl(field,
                                           indent_level=indent_level + 1,
                                           parent=obj,
                                           name=field_name)
            write('%s: %s', field_name, rendered_field)

        # Special case - empty non-union struct is rendered as empty map
        if first_field and not uavcan.is_union(obj):
            if indent_level > 0:
                indent_newline()
            write('{}')

    # ArrayValue
    elif isinstance(obj, ArrayValue):
        t = uavcan.get_uavcan_data_type(obj)
        if t.value_type.category == t.value_type.CATEGORY_PRIMITIVE:

            def is_nice_character(ch):
                if 32 <= ch <= 126:
                    return True
                if ch in b'\n\r\t':
                    return True
                return False

            as_bytes = '[%s]' % ', '.join([
                _to_yaml_impl(
                    x, indent_level=indent_level + 1, uavcan_type=t.value_type)
                for x in obj
            ])
            if t.is_string_like and all(map(is_nice_character, obj)):
                write('%r # ', obj.decode())
            write(as_bytes)
        else:
            if len(obj) == 0:
                write('[]')
            else:
                for x in obj:
                    indent_newline()
                    write(
                        '- %s',
                        _to_yaml_impl(x,
                                      indent_level=indent_level + 1,
                                      uavcan_type=t.value_type))

    # Primitive types
    elif isinstance(obj, float):
        assert uavcan_type is not None
        float_fmt = {
            16: '%.4f',
            32: '%.6f',
            64: '%.9f',
        }[uavcan_type.bitlen]
        write(float_fmt, obj)
    elif isinstance(obj, bool):
        write('%s', 'true' if obj else 'false')
    elif isinstance(obj, int):
        write('%s', obj)
        if parent is not None and name is not None:
            resolved_name = value_to_constant_name(parent, name)
            if isinstance(resolved_name, str):
                write(' # %s', resolved_name)

    # Non-printable types
    elif isinstance(obj, VoidValue):
        pass

    # Unknown types
    else:
        raise ValueError('Cannot generate YAML representation for %r' %
                         type(obj))

    return buf.getvalue()
Example #19
0
def _to_yaml_impl(obj, indent_level=0, parent=None, name=None, uavcan_type=None):
    buf = StringIO()

    def write(fmt, *args):
        buf.write((fmt % args) if len(args) else fmt)

    def indent_newline():
        buf.write(os.linesep + ' ' * 2 * indent_level)

    # Decomposing PrimitiveValue to value and type. This is ugly but it's by design...
    if isinstance(obj, PrimitiveValue):
        uavcan_type = uavcan.get_uavcan_data_type(obj)
        obj = obj.value

    # CompoundValue
    if isinstance(obj, CompoundValue):
        first_field = True

        # Rendering all fields than can be rendered
        for field_name, field in uavcan.get_fields(obj).items():
            if uavcan.is_union(obj) and uavcan.get_active_union_field(obj) != field_name:
                continue
            if isinstance(field, VoidValue):
                continue
            if (first_field and indent_level > 0) or not first_field:
                indent_newline()
            first_field = False
            rendered_field = _to_yaml_impl(field, indent_level=indent_level + 1, parent=obj, name=field_name)
            write('%s: %s', field_name, rendered_field)

        # Special case - empty non-union struct is rendered as empty map
        if first_field and not uavcan.is_union(obj):
            if indent_level > 0:
                indent_newline()
            write('{}')

    # ArrayValue
    elif isinstance(obj, ArrayValue):
        t = uavcan.get_uavcan_data_type(obj)
        if t.value_type.category == t.value_type.CATEGORY_PRIMITIVE:
            def is_nice_character(ch):
                if 32 <= ch <= 126:
                    return True
                if ch in b'\n\r\t':
                    return True
                return False

            as_bytes = '[%s]' % ', '.join([_to_yaml_impl(x, indent_level=indent_level + 1, uavcan_type=t.value_type)
                                          for x in obj])
            if t.is_string_like and all(map(is_nice_character, obj)):
                write('%r # ', obj.decode())
            write(as_bytes)
        else:
            if len(obj) == 0:
                write('[]')
            else:
                for x in obj:
                    indent_newline()
                    write('- %s', _to_yaml_impl(x, indent_level=indent_level + 1, uavcan_type=t.value_type))

    # Primitive types
    elif isinstance(obj, float):
        assert uavcan_type is not None
        float_fmt = {
            16: '%.4f',
            32: '%.6f',
            64: '%.9f',
        }[uavcan_type.bitlen]
        write(float_fmt, obj)
    elif isinstance(obj, bool):
        write('%s', 'true' if obj else 'false')
    elif isinstance(obj, int):
        write('%s', obj)
        if parent is not None and name is not None:
            resolved_name = value_to_constant_name(parent, name)
            if isinstance(resolved_name, str):
                write(' # %s', resolved_name)

    # Non-printable types
    elif isinstance(obj, VoidValue):
        pass

    # Unknown types
    else:
        raise ValueError('Cannot generate YAML representation for %r' % type(obj))

    return buf.getvalue()
def get_union_value(u):
    return getattr(u, uavcan.get_active_union_field(u))
    def __init__(self, parent, node, target_node_id, param_struct,
                 update_callback):
        super(ConfigParamEditWindow, self).__init__(parent)
        self.setWindowTitle('Edit configuration parameter')
        self.setModal(True)

        self._node = node
        self._target_node_id = target_node_id
        self._param_struct = param_struct
        self._update_callback = update_callback

        min_val = get_union_value(param_struct.min_value)
        if 'uavcan.protocol.param.Empty' in str(min_val):
            min_val = None

        max_val = get_union_value(param_struct.max_value)
        if 'uavcan.protocol.param.Empty' in str(max_val):
            max_val = None

        value = get_union_value(param_struct.value)
        self._value_widget = None
        value_type = uavcan.get_active_union_field(param_struct.value)

        if value_type == 'integer_value':
            min_val = min_val if min_val is not None else -0x8000000000000000
            max_val = max_val if max_val is not None else 0x7FFFFFFFFFFFFFFF
            if min_val >= -0x80000000 and \
               max_val <= +0x7FFFFFFF:
                self._value_widget = QSpinBox(self)
                self._value_widget.setMaximum(max_val)
                self._value_widget.setMinimum(min_val)
                self._value_widget.setValue(value)
        if value_type == 'real_value':
            min_val = round_float(
                min_val) if min_val is not None else -3.4028235e+38
            max_val = round_float(
                max_val) if max_val is not None else 3.4028235e+38
            value = round_float(value)
        if value_type == 'boolean_value':
            self._value_widget = QCheckBox(self)
            self._value_widget.setChecked(bool(value))

        if self._value_widget is None:
            self._value_widget = QLineEdit(self)
            self._value_widget.setText(str(value))
        self._value_widget.setFont(get_monospace_font())

        layout = QGridLayout(self)

        def add_const_field(label, *values):
            row = layout.rowCount()
            layout.addWidget(QLabel(label, self), row, 0)
            if len(values) == 1:
                layout.addWidget(FieldValueWidget(self, values[0]), row, 1)
            else:
                sub_layout = QHBoxLayout(self)
                for idx, v in enumerate(values):
                    sub_layout.addWidget(FieldValueWidget(self, v))
                layout.addLayout(sub_layout, row, 1)

        add_const_field('Name', param_struct.name)
        add_const_field(
            'Type',
            uavcan.get_active_union_field(param_struct.value).replace(
                '_value', ''))
        add_const_field('Min/Max', min_val, max_val)
        add_const_field('Default', render_union(param_struct.default_value))

        layout.addWidget(QLabel('Value', self), layout.rowCount(), 0)
        layout.addWidget(self._value_widget, layout.rowCount() - 1, 1)

        fetch_button = make_icon_button('refresh',
                                        'Read parameter from the node',
                                        self,
                                        text='Fetch',
                                        on_clicked=self._do_fetch)
        set_default_button = make_icon_button('fire-extinguisher',
                                              'Restore default value',
                                              self,
                                              text='Restore',
                                              on_clicked=self._restore_default)
        send_button = make_icon_button('flash',
                                       'Send parameter to the node',
                                       self,
                                       text='Send',
                                       on_clicked=self._do_send)
        cancel_button = make_icon_button(
            'remove',
            'Close this window; unsent changes will be lost',
            self,
            text='Cancel',
            on_clicked=self.close)

        controls_layout = QGridLayout(self)
        controls_layout.addWidget(fetch_button, 0, 0)
        controls_layout.addWidget(send_button, 0, 1)
        controls_layout.addWidget(set_default_button, 1, 0)
        controls_layout.addWidget(cancel_button, 1, 1)
        layout.addLayout(controls_layout, layout.rowCount(), 0, 1, 2)

        self._status_bar = QStatusBar(self)
        self._status_bar.setSizeGripEnabled(False)
        layout.addWidget(self._status_bar, layout.rowCount(), 0, 1, 2)

        left, top, right, bottom = layout.getContentsMargins()
        bottom = 0
        layout.setContentsMargins(left, top, right, bottom)

        self.setLayout(layout)
Example #22
0
def get_union_value(u):
    return getattr(u, uavcan.get_active_union_field(u))
Example #23
0
    def __init__(self, parent, node, target_node_id, param_struct, update_callback):
        super(ConfigParamEditWindow, self).__init__(parent)
        self.setWindowTitle("Edit configuration parameter")
        self.setModal(True)

        self._node = node
        self._target_node_id = target_node_id
        self._param_struct = param_struct
        self._update_callback = update_callback

        min_val = get_union_value(param_struct.min_value)
        if "uavcan.protocol.param.Empty" in str(min_val):
            min_val = None

        max_val = get_union_value(param_struct.max_value)
        if "uavcan.protocol.param.Empty" in str(max_val):
            max_val = None

        value = get_union_value(param_struct.value)
        self._value_widget = None
        value_type = uavcan.get_active_union_field(param_struct.value)

        if value_type == "integer_value":
            min_val = min_val if min_val is not None else -0x8000000000000000
            max_val = max_val if max_val is not None else 0x7FFFFFFFFFFFFFFF
            if min_val >= -0x80000000 and max_val <= +0x7FFFFFFF:
                self._value_widget = QSpinBox(self)
                self._value_widget.setMaximum(max_val)
                self._value_widget.setMinimum(min_val)
                self._value_widget.setValue(value)
        if value_type == "real_value":
            min_val = round_float(min_val) if min_val is not None else -3.4028235e38
            max_val = round_float(max_val) if max_val is not None else 3.4028235e38
            value = round_float(value)
        if value_type == "boolean_value":
            self._value_widget = QCheckBox(self)
            self._value_widget.setChecked(bool(value))

        if self._value_widget is None:
            self._value_widget = QLineEdit(self)
            self._value_widget.setText(str(value))
        self._value_widget.setFont(get_monospace_font())

        layout = QGridLayout(self)

        def add_const_field(label, *values):
            row = layout.rowCount()
            layout.addWidget(QLabel(label, self), row, 0)
            if len(values) == 1:
                layout.addWidget(FieldValueWidget(self, values[0]), row, 1)
            else:
                sub_layout = QHBoxLayout(self)
                for idx, v in enumerate(values):
                    sub_layout.addWidget(FieldValueWidget(self, v))
                layout.addLayout(sub_layout, row, 1)

        add_const_field("Name", param_struct.name)
        add_const_field("Type", uavcan.get_active_union_field(param_struct.value).replace("_value", ""))
        add_const_field("Min/Max", min_val, max_val)
        add_const_field("Default", render_union(param_struct.default_value))

        layout.addWidget(QLabel("Value", self), layout.rowCount(), 0)
        layout.addWidget(self._value_widget, layout.rowCount() - 1, 1)

        fetch_button = make_icon_button(
            "refresh", "Read parameter from the node", self, text="Fetch", on_clicked=self._do_fetch
        )
        set_default_button = make_icon_button(
            "fire-extinguisher", "Restore default value", self, text="Restore", on_clicked=self._restore_default
        )
        send_button = make_icon_button(
            "flash", "Send parameter to the node", self, text="Send", on_clicked=self._do_send
        )
        cancel_button = make_icon_button(
            "remove", "Close this window; unsent changes will be lost", self, text="Cancel", on_clicked=self.close
        )

        controls_layout = QGridLayout(self)
        controls_layout.addWidget(fetch_button, 0, 0)
        controls_layout.addWidget(send_button, 0, 1)
        controls_layout.addWidget(set_default_button, 1, 0)
        controls_layout.addWidget(cancel_button, 1, 1)
        layout.addLayout(controls_layout, layout.rowCount(), 0, 1, 2)

        self._status_bar = QStatusBar(self)
        self._status_bar.setSizeGripEnabled(False)
        layout.addWidget(self._status_bar, layout.rowCount(), 0, 1, 2)

        left, top, right, bottom = layout.getContentsMargins()
        bottom = 0
        layout.setContentsMargins(left, top, right, bottom)

        self.setLayout(layout)