def config_poll(layer: int, position: int, keys: list) -> object: """ Construct CFG-VALGET message from an array of configuration database keys, which can be in int (keyID) or str (keyname) format. :param int layer: memory layer (0=RAM, 1=BBR, 2=Flash, 7 = Default) :param int position: number of keys to skip before returning result :param list keys: array of up to 64 keys as int (keyID) or str (keyname) :return: UBXMessage CFG-VALGET :rtype: UBXMessage :raises: UBXMessageError """ num = len(keys) if num > 64: raise ube.UBXMessageError( f"Number of configuration keys {num} exceeds maximum of 64") version = val2bytes(0, ubt.U1) layer = val2bytes(layer, ubt.U1) position = val2bytes(position, ubt.U2) payload = version + layer + position lis = b"" for key in keys: if isinstance(key, str): # if keyname as a string (key, _) = cfgname2key(key) # lookup keyID keyb = val2bytes(key, ubt.U4) lis = lis + keyb return UBXMessage("CFG", "CFG-VALGET", ubt.POLL, payload=payload + lis)
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
def config_del(layers: int, transaction: int, keys: list) -> object: """ Construct CFG-VALDEL message from an array of configuration database keys, which can be in int (keyID) or str (keyname) format. :param int layers: memory layer(s) (2=BBR, 4=Flash) :param int transaction: 0=no txn, 1=start txn, 2=continue txn, 3=apply txn :param list keys: array of up to 64 keys as int (keyID) or string (keyname) :return: UBXMessage CFG-VALDEL :rtype: UBXMessage :raises: UBXMessageError """ num = len(keys) if num > 64: raise ube.UBXMessageError( f"Number of configuration keys {num} exceeds maximum of 64") version = val2bytes(0 if transaction == 0 else 1, ubt.U1) layers = val2bytes(layers, ubt.U1) transaction = val2bytes(transaction, ubt.U1) payload = version + layers + transaction + b"\x00" lis = b"" for key in keys: if isinstance(key, str): # if keyname as a string (key, _) = cfgname2key(key) # lookup keyID keyb = val2bytes(key, ubt.U4) lis = lis + keyb return UBXMessage("CFG", "CFG-VALDEL", ubt.SET, payload=payload + lis)
def _do_len_checksum(self): """ Calculate and format payload length and checksum as bytes.""" if self._payload is None: self._length = val2bytes(0, ubt.U2) self._checksum = calc_checksum(self._ubxClass + self._ubxID + self._length) else: self._length = val2bytes(len(self._payload), ubt.U2) self._checksum = calc_checksum(self._ubxClass + self._ubxID + self._length + self._payload)
def _get_relposned_version(self, **kwargs) -> dict: """ Select appropriate NAV-RELPOSNED payload definition by checking value of 'version' attribute (1st byte of payload). :param kwargs: optional payload key/value pairs :return: dictionary representing payload definition :rtype: dict :raises: UBXMessageError """ # pylint: disable=no-self-use if "version" in kwargs: ver = val2bytes(kwargs["version"], ubt.U1) elif "payload" in kwargs: ver = kwargs["payload"][0:1] else: raise ube.UBXMessageError( "NAV-RELPOSNED message definitions must include version or payload keyword" ) if ver == b"\x00": pdict = ubg.UBX_PAYLOADS_GET["NAV-RELPOSNED-V0"] else: pdict = ubg.UBX_PAYLOADS_GET["NAV-RELPOSNED"] return pdict
def _get_rxmrlm_version(self, **kwargs) -> dict: """ Select appropriate RXM-PMP payload definition by checking value of 'type' attribute (2nd byte of payload). :param kwargs: optional payload key/value pairs :return: dictionary representing payload definition :rtype: dict :raises: UBXMessageError """ # pylint: disable=no-self-use if "type" in kwargs: typ = val2bytes(kwargs["type"], ubt.U1) elif "payload" in kwargs: typ = kwargs["payload"][1:2] else: raise ube.UBXMessageError( "RXM-RLM message definitions must include type or payload keyword" ) if typ == b"\x01": pdict = ubg.UBX_PAYLOADS_GET["RXM-RLM-S"] # short else: pdict = ubg.UBX_PAYLOADS_GET["RXM-RLM-L"] # long return pdict
def _get_mga_version(self, mode: int, **kwargs) -> dict: """ Select appropriate MGA payload definition by checking value of 'type' attribute (1st byte of payload). :param str mode: mode (0=GET, 1=SET, 2=POLL) :param kwargs: optional payload key/value pairs :return: dictionary representing payload definition :rtype: dict :raises: UBXMessageError """ if "type" in kwargs: typ = val2bytes(kwargs["type"], ubt.U1) elif "payload" in kwargs: typ = kwargs["payload"][0:1] else: raise ube.UBXMessageError( "MGA message definitions must include type or payload keyword") identity = ubt.UBX_MSGIDS[self._ubxClass + self._ubxID + typ] if mode == ubt.SET: pdict = ubs.UBX_PAYLOADS_SET[identity] else: pdict = ubg.UBX_PAYLOADS_GET[identity] return pdict
def testVal2Bytes(self): # test conversion of value to bytes INPUTS = [ (2345, ubt.U2), (2345, ubt.E2), (1, ubt.L), (-2346789, ubt.I4), (b"\x44\x55", ubt.X2), (23.12345678, ubt.R4), (-23.12345678912345, ubt.R8), ([1, 2, 3, 4, 5], "A005"), ] EXPECTED_RESULTS = [ b"\x29\x09", b"\x29\x09", b"\x01", b"\xdb\x30\xdc\xff", b"\x44\x55", b"\xd7\xfc\xb8\x41", b"\x1f\xc1\x37\xdd\x9a\x1f\x37\xc0", b"\x01\x02\x03\x04\x05", ] for i, inp in enumerate(INPUTS): (val, att) = inp res = val2bytes(val, att) self.assertEqual(res, EXPECTED_RESULTS[i])
def __str__(self) -> str: """ Human readable representation. :return: human readable representation :rtype: str """ clsid = None umsg_name = self.identity if self.payload is None: return f"<UBX({umsg_name})>" stg = f"<UBX({umsg_name}, " for i, att in enumerate(self.__dict__): if att[0] != "_": # only show public attributes val = self.__dict__[att] if att[0:6] == "gnssId": # attribute is a GNSS ID val = gnss2str(val) # get string representation e.g. 'GPS' if att == "iTOW": # attribute is a GPS Time of Week val = itow2utc(val) # show time in UTC format # if it's an ACK-ACK or ACK-NAK, we show what it's acknowledging in plain text if self._ubxClass == b"\x05": # ACK if att == "clsID": clsid = val2bytes(val, ubt.U1) val = ubt.UBX_CLASSES[clsid] if att == "msgID" and clsid: msgid = val2bytes(val, ubt.U1) val = ubt.UBX_MSGIDS[clsid + msgid] # if it's a CFG-MSG, we show what message class/id it refers to in plain text if self._ubxClass == b"\x06" and self._ubxID == b"\x01": # CFG-MSG if att == "msgClass": clsid = val2bytes(val, ubt.U1) val = ubt.UBX_CLASSES[clsid] if att == "msgID" and clsid: msgid = val2bytes(val, ubt.U1) val = ubt.UBX_MSGIDS[clsid + msgid] stg += att + "=" + str(val) if i < len(self.__dict__) - 1: stg += ", " stg += ")>" return stg
def config_set(layers: int, transaction: int, cfgData: list) -> object: """ Construct CFG-VALSET message from an array of configuration database (key, value) tuples. Keys can be in int (keyID) or str (keyname) format. :param int layers: memory layer(s) (1=RAM, 2=BBR, 4=Flash) :param int transaction: 0=no txn, 1=start txn, 2=continue txn, 3=apply txn :param list cfgData: list of up to 64 tuples (key, value) :return: UBXMessage CFG-VALSET :rtype: UBXMessage :raises: UBXMessageError """ num = len(cfgData) if num > 64: raise ube.UBXMessageError( f"Number of configuration tuples {num} exceeds maximum of 64") version = val2bytes(0 if transaction == 0 else 1, ubt.U1) layers = val2bytes(layers, ubt.U1) transaction = val2bytes(transaction, ubt.U1) payload = version + layers + transaction + b"\x00" lis = b"" for cfgItem in cfgData: att = "" (key, val) = cfgItem if isinstance(key, str): # if key is a string (keyname) (key, att) = cfgname2key(key) # lookup keyID & attribute type else: (_, att) = cfgkey2name(key) # lookup attribute type keyb = val2bytes(key, ubt.U4) valb = val2bytes(val, att) lis = lis + keyb + valb return UBXMessage("CFG", "CFG-VALSET", ubt.SET, payload=payload + lis)
def testVal2Bytes(self): # test invalid attribute type EXPECTED_ERROR = "Unknown attribute type Z001" with self.assertRaisesRegex(UBXTypeError, EXPECTED_ERROR): val2bytes(1, "Z001")