Beispiel #1
0
    def decode_api(self, data):
        """
        Decodes the given data and returns the result.

        This function allows for non-registered code to call the same decoding
        code as is used to parse data passed to the data_callback function.

        Args:
            data: (bytearray) Binary packetized telemetry data to decode

        Returns:
            Parsed version of the input data in the form of a PktData object
            or None if the data is not decodable
        """
        ptr = 0

        # Decode Pkt ID here...
        id_obj = U16Type()
        id_obj.deserialize(data, ptr)
        ptr += id_obj.getSize()
        pkt_id = id_obj.val

        # Decode time...
        pkt_time = TimeType()
        pkt_time.deserialize(data, ptr)
        ptr += pkt_time.getSize()

        if pkt_id not in self.__dict:
            # Don't crash if can't find pkt. Just notify and keep going
            print("Packet decode error: id %d not in dictionary. Time=%s" %
                  (pkt_id, pkt_time.to_readable()))
            print("Full pkt = \n")
            for i in data:
                print("0x%02x" % ord(i))

            return None

        # Retrieve the template instance for this channel
        pkt_temp = self.__dict[pkt_id]

        ch_temps = pkt_temp.get_ch_list()

        ch_data_objs = []
        for ch_temp in ch_temps:
            val_obj = self.decode_ch_val(data, ptr, ch_temp)
            ptr += val_obj.getSize()
            ch_data_objs.append(ChData(val_obj, pkt_time, ch_temp))

        return PktData(ch_data_objs, pkt_time, pkt_temp)
Beispiel #2
0
class CmdData(sys_data.SysData):
    """The CmdData class stores a specific command"""
    def __init__(self, cmd_args, cmd_temp, cmd_time=None):
        """
        Constructor.

        Args:
            cmd_args: The arguments for the event. Should match the types of the
                      arguments in the cmd_temp object. Should be a tuple.
            cmd_temp: Command Template instance for this command (this provides
                      the opcode and argument types are stored)
            cmd_time: The time the event should occur. This is for sequences.
                      Should be a TimeType object with time base=TB_DONT_CARE

        Returns:
            An initialized CmdData object
        """
        super().__init__()
        self.id = cmd_temp.get_id()
        self.template = cmd_temp
        self.arg_vals = cmd_args

        self.args = [deepcopy(typ) for (_, _, typ) in self.template.arguments]
        self.arg_names = [name for (name, _, _) in self.template.arguments]

        if cmd_time:
            self.time = cmd_time
        else:
            self.time = TimeType(TimeBase["TB_DONT_CARE"].value)

        errors = []
        for val, typ in zip(self.arg_vals, self.args):
            try:
                self.convert_arg_value(val, typ)
                errors.append("")
            except Exception as exc:
                errors.append(str(exc))
        # If any errors occur, then raise a aggregated error
        if [error for error in errors if error != ""]:
            raise CommandArgumentsException(errors)

    def get_template(self):
        """Get the template class associate with this specific data object

        Returns:
            Template -- The template class for this data object
        """

        return self.template

    def get_id(self):
        """Get the ID associate with the template of this data object

        Returns:
            An ID number
        """

        return self.id

    def get_arg_vals(self):
        """Get the values for each argument in a command.

        Returns:
            list -- a list of value objects that were used in this data object.
        """

        return self.arg_vals

    def get_args(self):
        """Get the arguments associate with the template of this data object

        Returns:
            list -- A list of type objects representing the arguments of the template of this data object (in order)
        """

        return self.args

    def get_str(self, time_zone=None, verbose=False, csv=False):
        """
        Convert the command data to a string

        Args:
            time_zone: (tzinfo, default=None) Timezone to print time in. If
                      time_zone=None, use local time.
            verbose: (boolean, default=False) Prints extra fields if True
            csv: (boolean, default=False) Prints each field with commas between
                                          if true

        Returns:
            String version of the command data
        """
        time_str = self.time.to_readable(time_zone)
        raw_time_str = str(self.time)
        name = self.template.get_full_name()

        if self.args is None:
            arg_str = "EMPTY COMMAND OBJ"
        else:
            # The arguments are currently serializable objects which cannot be
            # used to fill in a format string. Convert them to values that can be
            arg_val_list = [arg_obj.val for arg_obj in self.args]

            arg_str = " ".join(str(arg_val_list))

        if verbose and csv:
            return "%s,%s,%s,%d,%s" % (time_str, raw_time_str, name, self.id,
                                       arg_str)
        elif verbose and not csv:
            return "%s: %s (%d) %s : %s" % (
                time_str,
                name,
                self.id,
                raw_time_str,
                arg_str,
            )
        elif not verbose and csv:
            return "{},{},{}".format(time_str, name, arg_str)
        else:
            return "{}: {} : {}".format(time_str, name, arg_str)

    def convert_arg_value(self, arg_val, arg_type):
        if arg_val is None:
            raise CommandArgumentException(
                "Argument value could not be converted to type object")
        if isinstance(arg_type, BoolType):
            if arg_val == "False":
                av = False
            else:
                av = True
            arg_type.val = av
        elif isinstance(arg_type, EnumType):
            arg_type.val = arg_val
        elif isinstance(arg_type, (F64Type, F32Type)):
            arg_type.val = float(arg_val)
        elif isinstance(
                arg_type,
            (I64Type, U64Type, I32Type, U32Type, I16Type, U16Type, I8Type,
             U8Type),
        ):
            arg_type.val = int(arg_val, 0)
        elif isinstance(arg_type, StringType):
            arg_type.val = arg_val
        # Cannot handle serializable or array argument inputs
        elif isinstance(arg_type, (SerializableType, ArrayType)):
            pass
        else:
            raise CommandArgumentException(
                "Argument value could not be converted to type object")

    def __str__(self):
        arg_str = ""
        for name, typ in zip(self.arg_names, self.args):
            arg_str += ("%s : %s |") % (name, str(typ.val))
        arg_str = "w/ args | " + arg_str

        arg_info = "%s " % self.template.mnemonic

        if len(self.args) > 0:
            return arg_info + arg_str
        else:
            return arg_info