Beispiel #1
0
    def parse(message: bytes, validate: bool = False, mode: int = 0) -> 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 bool validate: validate message length and checksum (False (default), True)
        :param int mode: message mode (0=GET (default), 1=SET, 2=POLL)
        :return: UBXMessage object
        :rtype: UBXMessage
        :raises: UBXParseError (if data stream contains invalid data or unknown message type)

        """

        if mode not in (0, 1, 2):
            raise ube.UBXParseError(
                f"Invalid message mode {mode} - 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:
            if hdr != ubt.UBX_HDR:
                raise ube.UBXParseError((f"Invalid message header {hdr}"
                                         f" - should be {ubt.UBX_HDR}"))
            if leni != UBXMessage.bytes2val(lenb, ubt.U2):
                raise ube.UBXParseError(
                    (f"Invalid payload length {lenb}"
                     f" - should be {UBXMessage.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, mode)
            return UBXMessage(clsid, msgid, mode, payload=payload)
        except KeyError as err:
            modestr = ["GET", "SET", "POLL"][mode]
            raise ube.UBXParseError((
                f"Unknown message type clsid {clsid}, msgid {msgid}, mode {modestr}"
            )) from err
Beispiel #2
0
    def _do_len_checksum(self):
        """
        Calculate and format payload length and checksum as bytes."""

        if self._payload is None:
            self._length = self.val2bytes(0, ubt.U2)
            self._checksum = calc_checksum(self._ubxClass + self._ubxID + self._length)
        else:
            self._length = self.val2bytes(len(self._payload), ubt.U2)
            self._checksum = calc_checksum(
                self._ubxClass + self._ubxID + self._length + self._payload
            )
Beispiel #3
0
    def parse(message: bytes, *args, **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)
        :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", VALCKSUM)
        parsebf = kwargs.get("parsebitfield", True)
        decnavdat = kwargs.get("deocdenavdata", False)

        # accept args for backwards compatibility if no kwargs
        if len(kwargs) == 0:
            if len(args) > 0:
                validate = args[0]
            if len(args) > 1:
                msgmode = args[1]

        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 & VALCKSUM:
            if hdr != ubt.UBX_HDR:
                raise ube.UBXParseError((f"Invalid message header {hdr}"
                                         f" - should be {ubt.UBX_HDR}"))
            if leni != UBXMessage.bytes2val(lenb, ubt.U2):
                raise ube.UBXParseError(
                    (f"Invalid payload length {lenb}"
                     f" - should be {UBXMessage.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,
                              decodenavdata=decnavdat)
        except KeyError as err:
            modestr = ["GET", "SET", "POLL"][msgmode]
            raise ube.UBXParseError((
                f"Unknown message type clsid {clsid}, msgid {msgid}, mode {modestr}"
            )) from err
Beispiel #4
0
 def testCalcChecksum(self):
     res = calc_checksum(b'\x06\x01\x02\x00\xf0\x05')
     self.assertEqual(res, b'\xfe\x16')