Exemplo n.º 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
Exemplo n.º 2
0
    def read(self) -> (bytes, UBXMessage):
        """
        Read the binary data from the serial buffer.

        :return tuple of (raw_data as bytes, parsed_data as UBXMessage)
        :rtype tuple
        :raise UBXStreamError
        """

        stm = self._stream
        reading = True
        raw_data = None
        parsed_data = None

        byte1 = stm.read(2)  # read the first two bytes

        while reading:
            if len(byte1) < 2:  # EOF
                break
            if byte1 == ubt.UBX_HDR:  # it's a UBX message
                byten = stm.read(4)
                if len(byten) < 4:  # EOF
                    break
                clsid = byten[0:1]
                msgid = byten[1:2]
                lenb = byten[2:4]
                leni = int.from_bytes(lenb, "little", signed=False)
                byten = stm.read(leni + 2)
                if len(byten) < leni + 2:  # EOF
                    break
                plb = byten[0:leni]
                cksum = byten[leni:leni + 2]
                raw_data = ubt.UBX_HDR + clsid + msgid + lenb + plb + cksum
                parsed_data = UBXMessage.parse(raw_data)
                reading = False
            else:  # it's not a UBX message
                if self._validate:  # raise error and quit
                    nmeawarn = NMEAMSG if byte1 in (b"$G", b"$P") else ""
                    raise UBXStreamError(
                        f"Unknown data header {byte1}. {nmeawarn}")
                byte1 = stm.read(2)  # read next 2 bytes and carry on

        return (raw_data, parsed_data)
Exemplo n.º 3
0
    def read(self, ubxs, validate) -> [UBXMessage]:
        """Read the multiple UBX messages

        :return [UBXMessage]:

        """
        self._ubxs = ubxs
        self._validate = validate

        stm = self._ubxs
        lenm = len(stm)
        i = 0
        ubxs_parsed = []

        while i < lenm:
            byte1 = stm[i:i + 2]  # HEADER
            if len(byte1) < 2:  # EOF
                break
            if byte1 == ubt.UBX_HDR:  # it's a UBX message
                byten = stm[i + 2:i + 6]
                if len(byten) < 4:  # EOF
                    break
                clsid = byten[0:1]
                msgid = byten[1:2]
                lenb = byten[2:4]
                leni = int.from_bytes(lenb, "little", signed=False)
                byten = stm[i + 6:i + (6 + leni + 2)]
                if len(byten) < leni + 2:  # EOF
                    break
                plb = byten[0:leni]
                cksum = byten[leni:(leni + 2)]
                raw_data = ubt.UBX_HDR + clsid + msgid + lenb + plb + cksum
                parsed_data = UBXMessage.parse(raw_data)
                ubxs_parsed.append(parsed_data)
                i = i + 6 + leni + 2
            else:  # it's not a UBX message
                if self._validate:  # raise error and quit
                    raise UBXMessageError(f"Unknown data header {byte1}")
                i = i + 2  # read next 2 bytes and carry on

        return ubxs_parsed
Exemplo n.º 4
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