示例#1
0
    def _set_attribute_single(self, att: object, offset: int, key: str,
                              index: list, **kwargs) -> int:
        """
        Set individual attribute value, applying scaling where appropriate.

        EITHER
        :param str att: attribute type string e.g. 'U002'
        OR
        :param list att: if scaled, list of [attribute type string, scaling factor float]
        :param int offset: payload offset in bytes
        :param str key: attribute keyword
        :param list index: repeating group index array
        :param kwargs: optional payload key/value pairs
        :return: offset
        :rtype: int

        """
        # pylint: disable=no-member

        # if attribute is scaled
        scale = 1
        if isinstance(att, list):
            scale = att[1]
            att = att[0]

        # if attribute is part of a (nested) repeating group, suffix name with index
        keyr = key
        for i in index:  # one index for each nested level
            if i > 0:
                keyr += f"_{i:02d}"

        # determine attribute size (bytes)
        if att == ubt.CH:  # variable length string
            atts = len(self._payload)
        else:
            atts = attsiz(att)

        # if payload keyword has been provided,
        # use the appropriate offset of the payload
        if "payload" in kwargs:
            valb = self._payload[offset:offset + atts]
            if scale == 1:
                val = bytes2val(valb, att)
            else:
                val = round(bytes2val(valb, att) * scale, ubt.SCALROUND)
        else:
            # if individual keyword has been provided,
            # set to provided value, else set to
            # nominal value
            val = kwargs.get(keyr, nomval(att))
            if scale == 1:
                valb = val2bytes(val, att)
            else:
                valb = val2bytes(int(val / scale), att)
            self._payload += valb

        setattr(self, keyr, val)
        offset += atts

        return offset
示例#2
0
    def _set_attribute_cfgval(self, offset: int, **kwargs):
        """
        Parse CFG-VALGET payload to set of configuration
        key value pairs.

        :param int offset: payload offset
        :param **kwargs:  optional payload key/value pairs
        :raises: UBXMessageError

        """

        KEYLEN = 4
        if "payload" in kwargs:
            self._payload = kwargs["payload"]
        else:
            raise ube.UBXMessageError(
                "CFG-VALGET message definitions must include payload keyword")
        cfglen = len(self._payload[offset:])

        i = 0
        while offset < cfglen:
            if i == KEYLEN:
                key = int.from_bytes(self._payload[offset:offset + KEYLEN],
                                     "little",
                                     signed=False)
                (keyname, att) = cfgkey2name(key)
                atts = attsiz(att)
                valb = self._payload[offset + KEYLEN:offset + KEYLEN + atts]
                val = bytes2val(valb, att)
                setattr(self, keyname, val)
                i = 0
                offset += KEYLEN + atts

            else:
                i += 1
示例#3
0
 def testBytes2Val(self):  # test conversion of bytes to value
     INPUTS = [
         (b"\x29\x09", ubt.U2),
         (b"\x29\x09", ubt.E2),
         (b"\x01", ubt.L),
         (b"\xdb\x30\xdc\xff", ubt.I4),
         (b"\x44\x55", ubt.X2),
         (b"\xd7\xfc\xb8\x41", ubt.R4),
         (b"\x1f\xc1\x37\xdd\x9a\x1f\x37\xc0", ubt.R8),
         (b"\x01\x02\x03\x04\x05", "A005"),
     ]
     EXPECTED_RESULTS = [
         2345,
         2345,
         1,
         -2346789,
         b"\x44\x55",
         23.12345678,
         -23.12345678912345,
         [1, 2, 3, 4, 5],
     ]
     for i, inp in enumerate(INPUTS):
         (valb, att) = inp
         res = bytes2val(valb, att)
         if att == ubt.R4:
             self.assertAlmostEqual(res, EXPECTED_RESULTS[i], 6)
         elif att == ubt.R8:
             self.assertAlmostEqual(res, EXPECTED_RESULTS[i], 14)
         else:
             self.assertEqual(res, EXPECTED_RESULTS[i])
示例#4
0
    def length(self) -> int:
        """
        Payload length getter.

        :return: payload length as integer
        :rtype: int

        """

        return bytes2val(self._length, ubt.U2)
示例#5
0
    def parse(message: bytes, **kwargs) -> object:
        """
        Parse UBX byte stream to UBXMessage object.

        Includes option to validate incoming payload length and checksum
        (the UBXMessage constructor can calculate and assign its own values anyway).

        :param bytes message: binary message to parse
        :param int validate: (kwarg) validate cksum (VALCKSUM (1)=True (default), VALNONE (0)=False)
        :param int msgmode: (kwarg) message mode (0=GET (default), 1=SET, 2=POLL)
        :param bool parsebitfield: (kwarg) parse bitfields True (default)/False
        :return: UBXMessage object
        :rtype: UBXMessage
        :raises: UBXParseError (if data stream contains invalid data or unknown message type)

        """

        msgmode = kwargs.get("msgmode", ubt.GET)
        validate = kwargs.get("validate", ubt.VALCKSUM)
        parsebf = kwargs.get("parsebitfield", True)

        if msgmode not in (0, 1, 2):
            raise ube.UBXParseError(
                f"Invalid message mode {msgmode} - must be 0, 1 or 2")

        lenm = len(message)
        hdr = message[0:2]
        clsid = message[2:3]
        msgid = message[3:4]
        lenb = message[4:6]
        if lenb == b"\x00\x00":
            payload = None
            leni = 0
        else:
            payload = message[6:lenm - 2]
            leni = len(payload)
        ckm = message[lenm - 2:lenm]
        if payload is not None:
            ckv = calc_checksum(clsid + msgid + lenb + payload)
        else:
            ckv = calc_checksum(clsid + msgid + lenb)
        if validate & ubt.VALCKSUM:
            if hdr != ubt.UBX_HDR:
                raise ube.UBXParseError((f"Invalid message header {hdr}"
                                         f" - should be {ubt.UBX_HDR}"))
            if leni != bytes2val(lenb, ubt.U2):
                raise ube.UBXParseError(
                    (f"Invalid payload length {lenb}"
                     f" - should be {val2bytes(leni, ubt.U2)}"))
            if ckm != ckv:
                raise ube.UBXParseError((f"Message checksum {ckm}"
                                         f" invalid - should be {ckv}"))
        try:
            if payload is None:
                return UBXMessage(clsid, msgid, msgmode)
            return UBXMessage(
                clsid,
                msgid,
                msgmode,
                payload=payload,
                parsebitfield=parsebf,
            )
        except KeyError as err:
            modestr = ["GET", "SET", "POLL"][msgmode]
            raise ube.UBXParseError((
                f"Unknown message type clsid {clsid}, msgid {msgid}, mode {modestr}"
            )) from err
示例#6
0
 def testBytes2Val(self):  # test invalid attribute type
     EXPECTED_ERROR = "Unknown attribute type Z001"
     with self.assertRaisesRegex(UBXTypeError, EXPECTED_ERROR):
         bytes2val(b"\x01", "Z001")