diff --git a/.vscode/settings.json b/.vscode/settings.json index 01f803a..dd60674 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,5 @@ "editor.formatOnSave": true, "modulename": "${workspaceFolderBasename}", "distname": "${workspaceFolderBasename}", - "moduleversion": "1.2.37", + "moduleversion": "1.2.38", } \ No newline at end of file diff --git a/README.md b/README.md index 2774c22..bc8316c 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,8 @@ conda install -c conda-forge pyubx2 | POLL (0x02) | query input *to* the receiver | `ubxtypes_poll.py` | If you're simply streaming and/or parsing the *output* of a UBX receiver, the mode is implicitly GET. If you want to create -or parse an *input* (command or query) message, you must set the mode parameter to SET or POLL. +or parse an *input* (command or query) message, you must set the mode parameter to SET or POLL. If the parser mode is set to +0x03 (SETPOLL), `pyubx2` will automatically determine the applicable input mode (SET or POLL) based on the message payload. --- ## Reading (Streaming) @@ -116,7 +117,7 @@ The constructor accepts the following optional keyword arguments: * `quitonerror`: 0 = ignore errors, 1 = log errors and continue (default), 2 = (re)raise errors and terminate * `validate`: VALCKSUM (0x01) = validate checksum (default), VALNONE (0x00) = ignore invalid checksum or length * `parsebitfield`: 1 = parse bitfields ('X' type properties) as individual bit flags, where defined (default), 0 = leave bitfields as byte sequences -* `msgmode`: 0 = GET (default), 1 = SET, 2 = POLL +* `msgmode`: 0 = GET (default), 1 = SET, 2 = POLL, 3 = SETPOLL (automatically determine SET or POLL input mode) Example - Serial input. This example will output both UBX and NMEA messages: ```python @@ -159,7 +160,7 @@ The `parse()` method accepts the following optional keyword arguments: * `validate`: VALCKSUM (0x01) = validate checksum (default), VALNONE (0x00) = ignore invalid checksum or length * `parsebitfield`: 1 = parse bitfields as individual bit flags, where defined (default), 0 = leave bitfields as byte sequences -* `msgmode`: 0 = GET (default), 1 = SET, 2 = POLL +* `msgmode`: 0 = GET (default), 1 = SET, 2 = POLL, 3 = SETPOLL (automatically determine SET or POLL input mode) Example - output (GET) message: ```python diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1e872ce..e6e298a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,14 @@ # pyubx2 Release Notes -### RELEASE CANDIDATE 1.2.37 +### RELEASE CANDIDATE 1.2.38 + +CHANGES: + +1. Add val2sphp helper method to convert high precision (9dp) coordinate to separate standard and high precision components, as required by some CFG and NAV messages. +1. Add utc2itow helper method to convert utc datetime to GPS week number and time of week. +1. Add getinputmode helper to determinate mode of input UBX message (SET or POLL). Add new UBXReader msgmode of SETPOLL (0x03), which will automatically determine input mode. + +### RELEASE 1.2.37 CHANGES: diff --git a/examples/f9p_basestation.py b/examples/f9p_basestation.py index c1b0c95..4977856 100644 --- a/examples/f9p_basestation.py +++ b/examples/f9p_basestation.py @@ -17,13 +17,13 @@ :license: BSD 3-Clause """ -from math import trunc from serial import Serial -from pyubx2 import UBXMessage + +from pyubx2 import UBXMessage, val2sphp TMODE_SVIN = 1 TMODE_FIXED = 2 - +SHOW_PRESET = True # hide or show PyGPSClient preset string def send_msg(serial_out: Serial, ubx: UBXMessage): """ @@ -105,17 +105,8 @@ def config_fixed(acc_limit: int, lat: float, lon: float, height: float) -> UBXMe layers = 1 transaction = 0 acc_limit = int(round(acc_limit / 0.1, 0)) - - # separate standard and high precision parts of lat / lon - # and apply scaling factors - lat_7dp = trunc(lat * 1e7) / 1e7 - lat_hp = lat - lat_7dp - lat = int(round(lat_7dp / 1e-7, 0)) - lat_hp = int(round(lat_hp / 1e-9, 0)) - lon_7dp = trunc(lon * 1e7) / 1e7 - lon_hp = lon - lon_7dp - lon = int(round(lon_7dp / 1e-7, 0)) - lon_hp = int(round(lon_hp / 1e-9, 0)) + lats, lath = val2sphp(lat) + lons, lonh = val2sphp(lon) height = int(height) cfg_data = [ @@ -124,10 +115,10 @@ def config_fixed(acc_limit: int, lat: float, lon: float, height: float) -> UBXMe ("CFG_TMODE_FIXED_POS_ACC", acc_limit), ("CFG_TMODE_HEIGHT_HP", 0), ("CFG_TMODE_HEIGHT", height), - ("CFG_TMODE_LAT", lat), - ("CFG_TMODE_LAT_HP", lat_hp), - ("CFG_TMODE_LON", lon), - ("CFG_TMODE_LON_HP", lon_hp), + ("CFG_TMODE_LAT", lats), + ("CFG_TMODE_LAT_HP", lath), + ("CFG_TMODE_LON", lons), + ("CFG_TMODE_LON_HP", lonh), ] ubx = UBXMessage.config_set(layers, transaction, cfg_data) @@ -147,21 +138,22 @@ def config_fixed(acc_limit: int, lat: float, lon: float, height: float) -> UBXMe PORT_TYPE = "USB" # choose from "USB", "UART1", "UART2" BAUD = 38400 TIMEOUT = 5 - SHOW_PRESET = True # hide or show PyGPSClient preset string - TMODE = TMODE_SVIN # "TMODE_SVIN" or 1 = Survey-In, "TMODE_FIXED" or 2 = Fixed + + TMODE = TMODE_FIXED # "TMODE_SVIN" or 1 = Survey-In, "TMODE_FIXED" or 2 = Fixed ACC_LIMIT = 200 # accuracy in mm - # only used if TMODE = 1 ... + # only used if TMODE = SVIN ... SVIN_MIN_DUR = 90 # seconds - # only used if TMODE = 2 ... - ARP_LAT = 37.012345678 - ARP_LON = -115.012345678 + # only used if TMODE = FIXED ... + ARP_LAT = 12.123456789 + ARP_LON = -115.987654321 ARP_HEIGHT = 137000 # cm print(f"Configuring receiver on {PORT} @ {BAUD:,} baud.\n") with Serial(PORT, BAUD, timeout=TIMEOUT) as stream: + # configure RTCM3 outputs msg = config_rtcm(PORT_TYPE) send_msg(stream, msg) diff --git a/pyproject.toml b/pyproject.toml index 6442c63..3970fa3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "pyubx2" authors = [{ name = "semuadmin", email = "semuadmin@semuconsulting.com" }] maintainers = [{ name = "semuadmin", email = "semuadmin@semuconsulting.com" }] description = "UBX protocol parser and generator" -version = "1.2.37" +version = "1.2.38" license = { file = "LICENSE" } readme = "README.md" requires-python = ">=3.8" @@ -87,7 +87,7 @@ disable = """ [tool.pytest.ini_options] minversion = "7.0" -addopts = "--cov --cov-report term-missing --cov-fail-under 95" +addopts = "--cov --cov-report html --cov-fail-under 95" pythonpath = ["src"] testpaths = ["tests"] diff --git a/src/pyubx2/_version.py b/src/pyubx2/_version.py index 6fb0f67..cdf05ff 100644 --- a/src/pyubx2/_version.py +++ b/src/pyubx2/_version.py @@ -8,4 +8,4 @@ :license: BSD 3-Clause """ -__version__ = "1.2.37" +__version__ = "1.2.38" diff --git a/src/pyubx2/ubxhelpers.py b/src/pyubx2/ubxhelpers.py index bddaa2c..205c380 100644 --- a/src/pyubx2/ubxhelpers.py +++ b/src/pyubx2/ubxhelpers.py @@ -13,14 +13,19 @@ import struct from datetime import datetime, timedelta -from math import cos, pi, sin +from math import cos, pi, sin, trunc from pynmeagps.nmeatypes_core import NMEA_HDR import pyubx2.exceptions as ube import pyubx2.ubxtypes_configdb as ubcdb import pyubx2.ubxtypes_core as ubt -from pyubx2.ubxtypes_core import GNSSLIST, UBX_HDR +from pyubx2.ubxtypes_core import POLL, SET, UBX_HDR +from pyubx2.ubxtypes_decodes import FIXTYPE, GNSSLIST + +EPOCH0 = datetime(1980, 1, 6) # EPOCH start date +LEAPOFFSET = 18 # leap year offset in seconds, valid as from 1/1/2017 +SIW = 604800 # seconds in week = 3600*24*7 def att2idx(att: str) -> int: @@ -123,18 +128,33 @@ def attsiz(att: str) -> int: def itow2utc(itow: int) -> datetime.time: """ Convert GPS Time Of Week to UTC time - (UTC = GPS - 18 seconds; correct as from 1/1/2017). - :param int itow: GPS Time Of Week + :param int itow: GPS Time Of Week in milliseconds :return: UTC time hh.mm.ss :rtype: datetime.time """ - utc = datetime(1980, 1, 6) + timedelta(seconds=(itow / 1000) - 18) + utc = EPOCH0 + timedelta(seconds=(itow / 1000) - LEAPOFFSET) return utc.time() +def utc2itow(utc: datetime) -> tuple: + """ + Convert UTC datetime to GPS Week Number, Time Of Week + + :param datetime utc: datetime + :return: GPS Week Number, Time of Week in milliseconds + :rtype: tuple + + """ + + wno = int((utc - EPOCH0).total_seconds() / SIW) + sow = EPOCH0 + timedelta(seconds=wno * SIW) + itow = int(((utc - sow).total_seconds() + LEAPOFFSET) * 1000) + return wno, itow + + def gpsfix2str(fix: int) -> str: """ Convert GPS fix integer to descriptive string. @@ -145,19 +165,10 @@ def gpsfix2str(fix: int) -> str: """ - if fix == 5: - fixs = "TIME ONLY" - elif fix == 4: - fixs = "GPS + DR" - elif fix == 3: - fixs = "3D" - elif fix == 2: - fixs = "2D" - elif fix == 1: - fixs = "DR" - else: - fixs = "NO FIX" - return fixs + try: + return FIXTYPE[fix] + except KeyError: + return str(fix) def dop2str(dop: float) -> str: @@ -498,3 +509,50 @@ def escapeall(val: bytes) -> str: """ return "b'{}'".format("".join(f"\\x{b:02x}" for b in val)) + + +def val2sphp(val: float, scale: float = 1e-7) -> tuple: + """ + Convert a float value into separate standard and high precisions components, + multiplied by a scaling factor to render them as integers, as required by some + CFG and NAV messages. + + e.g. 48.123456789 becomes (481234567, 89) + + :param float val: value as float + :param float scale: scaling factor e.g. 1e-7 + :return: tuple of (standard precision, high precision) + :rtype: tuple + """ + + val = val / scale + val_sp = trunc(val) + val_hp = round((val - val_sp) * 100) + return val_sp, val_hp + + +def getinputmode(data: bytes) -> int: + """ + Return input message mode (SET or POLL). + + :param bytes data: raw UBX input message + :return: message mode (1 = SET, 2 = POLL) + :rtype: int + """ + + if ( + len(data) == 8 + or data[2:4] == b"\x06\x8b" # CFG-VALGET + or ( + data[2:4] + in ( + b"\x06\x01", + b"\x06\x02", + b"\x06\x03", + b"\x06\x31", + ) # CFG-INF, CFG-MSG, CFG-PRT, CFG-TP5 + and len(data) <= 10 + ) + ): + return POLL + return SET diff --git a/src/pyubx2/ubxmessage.py b/src/pyubx2/ubxmessage.py index 9b01c85..45c96f9 100644 --- a/src/pyubx2/ubxmessage.py +++ b/src/pyubx2/ubxmessage.py @@ -74,8 +74,8 @@ def __init__( self._parsebf = parsebitfield # parsing bitfields Y/N? self._scaling = scaling # apply scale factors Y/N? - if msgmode not in (0, 1, 2): - raise ube.UBXMessageError(f"Invalid msgmode {msgmode} - must be 0, 1 or 2.") + if msgmode not in (ubt.GET, ubt.SET, ubt.POLL): + raise ube.UBXMessageError(f"Invalid msgmode {msgmode} - must be 0, 1 or 2") # accommodate different formats of msgClass and msgID if isinstance(ubxClass, str) and isinstance( diff --git a/src/pyubx2/ubxreader.py b/src/pyubx2/ubxreader.py index 345a124..f49dd35 100644 --- a/src/pyubx2/ubxreader.py +++ b/src/pyubx2/ubxreader.py @@ -9,7 +9,9 @@ 'protfilter' governs which protocols (NMEA, UBX or RTCM3) are processed 'quitonerror' governs how errors are handled -'msgmode' indicates the type of UBX datastream (input GET, output SET, query POLL) +'msgmode' indicates the type of UBX datastream (output GET, input SET, query POLL) + +If msgmode set to SETPOLL, input mode will be automatically detected by parser. Created on 2 Oct 2020 @@ -32,14 +34,17 @@ UBXTypeError, ) from pyubx2.socket_stream import SocketStream -from pyubx2.ubxhelpers import bytes2val, calc_checksum, val2bytes +from pyubx2.ubxhelpers import bytes2val, calc_checksum, getinputmode, val2bytes from pyubx2.ubxmessage import UBXMessage from pyubx2.ubxtypes_core import ( ERR_LOG, ERR_RAISE, GET, NMEA_PROTOCOL, + POLL, RTCM3_PROTOCOL, + SET, + SETPOLL, U2, UBX_HDR, UBX_PROTOCOL, @@ -69,7 +74,7 @@ def __init__( """Constructor. :param datastream stream: input data stream - :param int msgmode: 0=GET, 1=SET, 2=POLL (0) + :param int msgmode: 0=GET, 1=SET, 2=POLL, 3=SETPOLL (0) :param int validate: 0 = ignore invalid checksum, 1 = validate checksum (1) :param int protfilter: protocol filter 1 = NMEA, 2 = UBX, 4 = RTCM3 (3) :param int quitonerror: 0 = ignore errors, 1 = log continue, 2 = (re)raise (1) @@ -97,9 +102,9 @@ def __init__( self._msgmode = msgmode self._parsing = parsing - if self._msgmode not in (0, 1, 2): + if self._msgmode not in (GET, SET, POLL, SETPOLL): raise UBXStreamError( - f"Invalid stream mode {self._msgmode} - must be 0, 1 or 2" + f"Invalid stream mode {self._msgmode} - must be 0, 1, 2 or 3" ) def __iter__(self): @@ -374,8 +379,10 @@ def parse( """ # pylint: disable=too-many-arguments - if msgmode not in (0, 1, 2): - raise UBXParseError(f"Invalid message mode {msgmode} - must be 0, 1 or 2") + if msgmode not in (GET, SET, POLL, SETPOLL): + raise UBXParseError( + f"Invalid message mode {msgmode} - must be 0, 1, 2 or 3" + ) lenm = len(message) hdr = message[0:2] @@ -410,6 +417,9 @@ def parse( (f"Message checksum {ckm}" f" invalid - should be {ckv}") ) try: + # if input message (SET or POLL), determine mode automatically + if msgmode == SETPOLL: + msgmode = getinputmode(message) # returns SET or POLL if payload is None: return UBXMessage(clsid, msgid, msgmode) return UBXMessage( diff --git a/src/pyubx2/ubxtypes_core.py b/src/pyubx2/ubxtypes_core.py index cdd532a..99d2a10 100644 --- a/src/pyubx2/ubxtypes_core.py +++ b/src/pyubx2/ubxtypes_core.py @@ -12,6 +12,7 @@ GET = 0 SET = 1 POLL = 2 +SETPOLL = 3 VALNONE = 0 VALCKSUM = 1 NMEA_PROTOCOL = 1 @@ -21,17 +22,6 @@ ERR_LOG = 1 ERR_IGNORE = 0 -GNSSLIST = { - 0: "GPS", - 1: "SBAS", - 2: "Galileo", - 3: "BeiDou", - 4: "IMES", - 5: "QZSS", - 6: "GLONASS", - 7: "NAVIC", -} - # scaling factor constants SCAL9 = 1e-9 # 0.000000001 SCAL8 = 1e-8 # 0.00000001 diff --git a/src/pyubx2/ubxtypes_decodes.py b/src/pyubx2/ubxtypes_decodes.py index a8665c7..ef88a1b 100644 --- a/src/pyubx2/ubxtypes_decodes.py +++ b/src/pyubx2/ubxtypes_decodes.py @@ -8,6 +8,17 @@ :author: semuadmin """ +GNSSLIST = { + 0: "GPS", + 1: "SBAS", + 2: "Galileo", + 3: "BeiDou", + 4: "IMES", + 5: "QZSS", + 6: "GLONASS", + 7: "NAVIC", +} + # UBX-CFG-DGNSS DGNSMODE = { 2: "RTK float", @@ -266,12 +277,12 @@ # UBX-NAV-PVT GPSFIX = FIXTYPE = { - 0: "no fix", - 1: "dead reckoning only", - 2: "2D fix", - 3: "3D fix", - 4: "GPS + dead reckoning combined", - 5: "Time only fix", + 0: "NO FIX", + 1: "DR", + 2: "2D", + 3: "3D", + 4: "GPS + DR", + 5: "TIME ONLY", } PSMSTATE = { 0: "PSM is not active", @@ -282,9 +293,9 @@ 5: "Inactive", } CARRSOLN = { - 0: "no RTK", - 1: "RTK float", - 2: "RTK fixed", + 0: "NO RTK", + 1: "RTK FLOAT", + 2: "RTK FIXED", } # UBX-NAV-SAT @@ -331,7 +342,7 @@ # UBX-NAV-SIG CORRSOURCE = { - 0: "none", + 0: "NONE", 1: "SBAS", 2: "BeiDou", 3: "RTCM2", diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index efb762c..35a505e 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -44,9 +44,9 @@ def tearDown(self): pass def testInvMode(self): # test invalid mode - EXPECTED_ERROR = "Invalid msgmode 3 - must be 0, 1 or 2" + EXPECTED_ERROR = "Invalid msgmode 4 - must be 0, 1 or 2" with self.assertRaisesRegex(UBXMessageError, EXPECTED_ERROR): - UBXMessage("CFG", "CFG-MSG", 3, msgClass=240, msgID=5) + UBXMessage("CFG", "CFG-MSG", 4, msgClass=240, msgID=5) def testAckCkT(self): # bad checksum EXPECTED_ERROR = "Message checksum (.*) invalid - should be (.*)" @@ -320,10 +320,10 @@ def testFill_CFGVALGET1( UBXMessage("CFG", "CFG-VALGET", GET, version=0, layer=0) def testParseMode(self): # test invalid parse message mode - EXPECTED_ERROR = "Invalid message mode 3 - must be 0, 1 or 2" + EXPECTED_ERROR = "Invalid message mode 4 - must be 0, 1, 2 or 3" with self.assertRaisesRegex(UBXParseError, EXPECTED_ERROR): UBXReader.parse( - b"\xb5b\x05\x01\x02\x00\x06\x01\x0f\x38", validate=VALCKSUM, msgmode=3 + b"\xb5b\x05\x01\x02\x00\x06\x01\x0f\x38", validate=VALCKSUM, msgmode=4 ) def testParseMode2(self): # test parser with incorrect mode for input message @@ -332,9 +332,9 @@ def testParseMode2(self): # test parser with incorrect mode for input message UBXReader.parse(self.mga_ini, validate=VALCKSUM, quitonerror=ERR_RAISE) def testStreamMode(self): # test invalid stream message mode - EXPECTED_ERROR = "Invalid stream mode 3 - must be 0, 1 or 2" + EXPECTED_ERROR = "Invalid stream mode 4 - must be 0, 1, 2 or 3" with self.assertRaisesRegex(UBXStreamError, EXPECTED_ERROR): - UBXReader(None, validate=VALCKSUM, msgmode=3) + UBXReader(None, validate=VALCKSUM, msgmode=4) def testVal2Bytes(self): # test invalid attribute type EXPECTED_ERROR = "Unknown attribute type Z001" diff --git a/tests/test_parse.py b/tests/test_parse.py index 831c4db..37cd6a2 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -11,7 +11,7 @@ import unittest -from pyubx2 import UBXMessage, UBXReader, VALCKSUM, VALNONE, SET +from pyubx2 import UBXMessage, UBXReader, VALCKSUM, VALNONE, SET, SETPOLL class ParseTest(unittest.TestCase): @@ -270,6 +270,20 @@ def testMGAINI2(self): # test parser of MGA-INI input message with args "", ) + def testSETPOLL(self): # test auto detection of SET or POLL mode + msg = UBXMessage.config_poll(0,0,["CFG_UART1_BAUDRATE", 0x40530001]).serialize() + res = UBXReader.parse(msg, msgmode=SETPOLL) + self.assertEqual( + str(res), + "", + ) + msg = UBXMessage.config_set(0,0,[("CFG_UART1_BAUDRATE", 9600), (0x40530001, 38400)]).serialize() + res = UBXReader.parse(msg, msgmode=SETPOLL) + self.assertEqual( + str(res), + "", + ) + def testESFSTATUS(self): # test parser of ESF-STATUS message res = UBXReader.parse(self.esf_status) # print(res) diff --git a/tests/test_static.py b/tests/test_static.py index 02fae30..cd54705 100644 --- a/tests/test_static.py +++ b/tests/test_static.py @@ -11,30 +11,32 @@ import os import unittest -import unittest - -from pyubx2 import UBXMessage, UBXReader, UBX_CLASSES, POLL +from datetime import datetime import pyubx2.ubxtypes_core as ubt +from pyubx2 import SET, POLL, UBX_CLASSES, UBXMessage, UBXReader from pyubx2.ubxhelpers import ( + att2idx, + att2name, + bytes2val, calc_checksum, - isvalid_checksum, - key_from_val, + cel2cart, + cfgkey2name, + cfgname2key, + dop2str, + escapeall, get_bits, - itow2utc, + getinputmode, gnss2str, - dop2str, gpsfix2str, + hextable, + isvalid_checksum, + itow2utc, + key_from_val, msgstr2bytes, - val2bytes, - bytes2val, - cfgkey2name, - cfgname2key, protocol, - hextable, - att2idx, - att2name, - cel2cart, - escapeall, + utc2itow, + val2bytes, + val2sphp, ) @@ -162,6 +164,11 @@ def testitow2utc(self): res = str(itow2utc(387092000)) self.assertEqual(res, "11:31:14") + def testutc2itow(self): + dt = datetime(2024,2,8,11,31,14) + res = utc2itow(dt) + self.assertEqual(res, (2300, 387092000)) + def testgnss2str(self): GNSS = { 0: "GPS", @@ -179,8 +186,8 @@ def testgnss2str(self): self.assertEqual(res, GNSS[i]) def testgps2str(self): - fixs = ["NO FIX", "DR", "2D", "3D", "GPS + DR", "TIME ONLY"] - for i, fix in enumerate(range(0, 6)): + fixs = ["NO FIX", "DR", "2D", "3D", "GPS + DR", "TIME ONLY", "6"] + for i, fix in enumerate(range(0, 7)): res = gpsfix2str(fix) self.assertEqual(res, fixs[i]) @@ -276,6 +283,27 @@ def testescapeall(self): print(res) self.assertEqual(res, EXPECTED_RESULT) + def testval2sphp(self): + res = val2sphp(100.123456789) + self.assertEqual(res, (1001234567,89)) + res = val2sphp(-13.987654321) + self.assertEqual(res, (-139876543,-21)) + res = val2sphp(5.9876543) + self.assertEqual(res, (59876543,0)) + + def testgetinputmode(self): + res = getinputmode(UBXMessage("CFG","CFG-ODO", POLL).serialize()) + self.assertEqual(res, POLL) + res = getinputmode(UBXMessage.config_poll(0,0,["CFG_UART1_BAUDRATE", 0x40530001]).serialize()) + self.assertEqual(res, POLL) + res = getinputmode(UBXMessage.config_set(0,0,[("CFG_UART1_BAUDRATE", 9600), (0x40530001, 115200)]).serialize()) + self.assertEqual(res, SET) + res = getinputmode(UBXMessage.config_del(0,0,["CFG_UART1_BAUDRATE", 0x40530001]).serialize()) + self.assertEqual(res, SET) + res = getinputmode(UBXMessage("CFG","CFG-INF", POLL, protocolID=1).serialize()) + self.assertEqual(res, POLL) + res = getinputmode(UBXMessage("CFG","CFG-INF", SET, protocolID=1, infMsgMask_01=1,infMsgMask_02=1).serialize()) + self.assertEqual(res, SET) if __name__ == "__main__": # import sys;sys.argv = ['', 'Test.testName']