def __init__(self, stream, *args, **kwargs): """Constructor. :param stream stream: input data stream :param bool ubxonly (kwarg): check for non-UBX data (False (ignore - default), True (reject)) :param int validate (kwarg): validate checksum (VALCKSUM (1)=True (default), VALNONE (0)=False) :param int msgmode (kwarg): message mode (0=GET (default), 1=SET, 2=POLL) :raises: UBXStreamError (if mode is invalid) """ ubx_only = kwargs.get("ubxonly", False) msgmode = kwargs.get("msgmode", 0) validate = kwargs.get("validate", VALCKSUM) # accept args for backwards compatibility if no kwargs if len(kwargs) == 0: if len(args) > 0: ubx_only = args[0] if len(args) > 1: msgmode = args[1] if msgmode not in (0, 1, 2): raise ube.UBXStreamError( f"Invalid stream mode {msgmode} - must be 0, 1 or 2") self._stream = stream self._ubx_only = ubx_only self._validate = validate self._mode = msgmode
def read(self) -> (bytes, UBXMessage): """ Read the binary data from the stream buffer. :return: tuple of (raw_data as bytes, parsed_data as UBXMessage) :rtype: tuple :raises: UBXStreamError (if ubxonly=True and stream includes non-UBX data) """ reading = True raw_data = None parsed_data = None byte1 = self._stream.read(1) # read the first byte while reading: is_ubx = False is_nmea = False if len(byte1) < 1: # EOF break if byte1 == b"\xb5": byte2 = self._stream.read(1) if len(byte2) < 1: # EOF break if byte2 == b"\x62": is_ubx = True if is_ubx: # it's a UBX message byten = self._stream.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 = self._stream.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 = self.parse(raw_data, validate=self._validate, msgmode=self._mode) reading = False else: # it's not a UBX message (NMEA or something else) prevbyte = byte1 byte1 = self._stream.read(1) if prevbyte == b"\x24" and byte1 in (b"\x47", b"\x50"): # "$G" or "$P" is_nmea = True # looks like an NMEA message if self._ubx_only: # raise error and quit nmeawarn = NMEAMSG if is_nmea else "" raise ube.UBXStreamError( f"Unknown data header {prevbyte + byte1}. {nmeawarn}") return (raw_data, parsed_data)
def __init__(self, stream, ubx_only: bool = False, mode: int = 0): """Constructor. :param stream stream: input data stream :param bool ubx_only: check for non-UBX data (False (ignore - default), True (reject)) :param int mode: message mode (0=GET (default), 1=SET, 2=POLL) :raises: UBXStreamError (if mode is invalid) """ if mode not in (0, 1, 2): raise ube.UBXStreamError( f"Invalid stream mode {mode} - must be 0, 1 or 2") self._stream = stream self._ubx_only = ubx_only self._mode = mode
def __init__(self, datastream, **kwargs): """Constructor. :param datastream stream: input data stream :param int quitonerror: (kwarg) 0 = ignore errors, 1 = log errors and continue, 2 = (re)raise errors (1) :param int protfilter: (kwarg) protocol filter 1 = NMEA, 2 = UBX, 4 = RTCM3 (3) :param int validate: (kwarg) 0 = ignore invalid checksum, 1 = validate checksum (1) :param int msgmode: (kwarg) 0=GET, 1=SET, 2=POLL (0) :param bool parsebitfield: (kwarg) 1 = parse bitfields, 0 = leave as bytes (1) :raises: UBXStreamError (if mode is invalid) """ self._stream = datastream self._protfilter = int( kwargs.get("protfilter", ubt.NMEA_PROTOCOL | ubt.UBX_PROTOCOL)) self._quitonerror = int(kwargs.get("quitonerror", ubt.ERR_LOG)) self._validate = int(kwargs.get("validate", ubt.VALCKSUM)) self._parsebf = int(kwargs.get("parsebitfield", True)) self._msgmode = int(kwargs.get("msgmode", 0)) if self._msgmode not in (0, 1, 2): raise ube.UBXStreamError( f"Invalid stream mode {self._msgmode} - must be 0, 1 or 2")
def __init__(self, stream, *args, **kwargs): """Constructor. :param stream stream: input data stream :param bool ubxonly: (kwarg) check non-UBX data (False (ignore - default), True (reject)) :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/false :raises: UBXStreamError (if mode is invalid) """ ubx_only = kwargs.get("ubxonly", False) validate = kwargs.get("validate", VALCKSUM) parsebf = kwargs.get("parsebitfield", True) decodenavdata = kwargs.get("decodenavdata", True) # TODO make default false in final msgmode = kwargs.get("msgmode", 0) # accept args for backwards compatibility if no kwargs if len(kwargs) == 0: if len(args) > 0: ubx_only = args[0] if len(args) > 1: msgmode = args[1] if msgmode not in (0, 1, 2): raise ube.UBXStreamError( f"Invalid stream mode {msgmode} - must be 0, 1 or 2") self._stream = stream self._ubx_only = ubx_only self._validate = validate self._mode = msgmode self._parsebf = parsebf self._decodenavdata = decodenavdata
def read(self) -> tuple: """ Read a single NMEA or UBX message from the stream buffer and return both raw and parsed data. 'protfilter' determines which protocols are parsed. 'quitonerror' determines whether to raise, log or ignore parsing errors. :return: tuple of (raw_data as bytes, parsed_data as UBXMessage or NMEAMessage) :rtype: tuple :raises: UBXStreamError (if unrecognised protocol in data stream) """ parsing = True try: while parsing: # loop until end of valid message or EOF raw_data = None parsed_data = None byte1 = self._read_bytes(1) # read the first byte # if not UBX, NMEA or RTCM3, discard and continue if byte1 not in (b"\xb5", b"\x24", b"\xd3"): continue byte2 = self._read_bytes(1) bytehdr = byte1 + byte2 # if it's a UBX message (b'\xb5\x62') if bytehdr == ubt.UBX_HDR: (raw_data, parsed_data) = self._parse_ubx(bytehdr) # if protocol filter passes UBX, return message, # otherwise discard and continue if self._protfilter & ubt.UBX_PROTOCOL: parsing = False else: continue # if it's an NMEA message ('$G' or '$P') elif bytehdr in ubt.NMEA_HDR: (raw_data, parsed_data) = self._parse_nmea(bytehdr) # if protocol filter passes NMEA, return message, # otherwise discard and continue if self._protfilter & ubt.NMEA_PROTOCOL: parsing = False else: continue # if it's a RTCM3 message # (byte1 = 0xd3; byte2 = 0b000000**) elif byte1 == b"\xd3" and (byte2[0] & ~0x03) == 0: (raw_data, parsed_data) = self._parse_rtcm3(bytehdr) # if protocol filter passes RTCM, return message, # otherwise discard and continue if self._protfilter & ubt.RTCM3_PROTOCOL: parsing = False else: continue # unrecognised protocol header else: if self._quitonerror == ubt.ERR_RAISE: raise ube.UBXStreamError( f"Unknown protocol {bytehdr}.") elif self._quitonerror == ubt.ERR_LOG: return (bytehdr, f"<UNKNOWN PROTOCOL(header={bytehdr})>") else: # ignore unknown protocol and continue continue except EOFError: return (None, None) return (raw_data, parsed_data)