def val2bytes(val, att: str) -> bytes: """ Convert value to bytes for given UBX attribute type. :param object val: attribute value e.g. 25 :param str att: attribute type e.g. 'U004' :return: attribute value as bytes :rtype: bytes :raises: UBXTypeError """ if att == ubt.CH: # single variable-length string (e.g. INF-NOTICE) return val.encode("utf-8", "backslashreplace") atts = attsiz(att) if atttyp(att) in ("C", "X"): # byte or char valb = val elif atttyp(att) in ("E", "L", "U"): # unsigned integer valb = val.to_bytes(atts, byteorder="little", signed=False) elif atttyp(att) == "I": # signed integer valb = val.to_bytes(atts, byteorder="little", signed=True) elif att == ubt.R4: # single precision floating point valb = struct.pack("<f", val) elif att == ubt.R8: # double precision floating point valb = struct.pack("<d", val) else: raise ube.UBXTypeError(f"Unknown attribute type {att}") return valb
def bytes2val(valb: bytes, att: str) -> object: """ Convert bytes to value for given UBX attribute type. :param bytes valb: attribute value in byte format e.g. b'\\\\x19\\\\x00\\\\x00\\\\x00' :param str att: attribute type e.g. 'U004' :return: attribute value as int, float, str or bytes :rtype: object :raises: UBXTypeError """ if att == ubt.CH: # single variable-length string (e.g. INF-NOTICE) val = valb.decode("utf-8", "backslashreplace") elif atttyp(att) in ("X", "C"): val = valb elif atttyp(att) in ("E", "L", "U"): # unsigned integer val = int.from_bytes(valb, "little", signed=False) elif atttyp(att) == "I": # signed integer val = int.from_bytes(valb, "little", signed=True) elif att == ubt.R4: # single precision floating point val = struct.unpack("<f", valb)[0] elif att == ubt.R8: # double precision floating point val = struct.unpack("<d", valb)[0] else: raise ube.UBXTypeError(f"Unknown attribute type {att}") return val
def nomval(att: str) -> object: """ Get nominal value for given UBX attribute type. :param str att: attribute type e.g. 'U004' :return: attribute value as int, float, str or bytes :rtype: object :raises: UBXTypeError """ if att == "CH": val = "" elif atttyp(att) in ("X", "C"): val = b"\x00" * attsiz(att) elif atttyp(att) == "R": val = 0.0 elif atttyp(att) in ("E", "I", "L", "U"): val = 0 else: raise ube.UBXTypeError(f"Unknown attribute type {att}") return val
def _set_attribute_single(self, att: str, offset: int, key: str, index: list, **kwargs) -> int: """ Set individual attribute value. :param str att: attribute type e.g. 'U002' :param int offset: payload offset :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 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 = keyr + "_{0:0=2d}".format(i) # 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] val = self.bytes2val(valb, att) else: # if individual attribute keyword has been provided if keyr in kwargs: val = kwargs[keyr] # else set attribute to nominal value (0) else: if atttyp(att) in ("X", "C"): # byte or char val = b"\x00" * atts else: val = 0 valb = self.val2bytes(val, att) self._payload += valb setattr(self, keyr, val) offset += atts return offset
def _do_valset(self): """ Send a CFG-VALSET message. :return: valid entry flag :rtype: bool """ valid_entry = True att = atttyp(self._cfgatt.get()) atts = attsiz(self._cfgatt.get()) val = self._cfgval.get() layers = self._cfglayer.get() if layers == "BBR": layers = 2 elif layers == "FLASH": layers = 4 else: layers = 1 try: if att in ("C", "X"): # byte or char if len(val) == atts * 2: # 2 hex chars per byte val = bytearray.fromhex(val) else: valid_entry = False elif att in ("E", "U"): # unsigned integer val = int(val) if val < 0: valid_entry = False elif att == "L": # bool val = int(val) if val not in (0, 1): valid_entry = False elif att == "I": # signed integer val = int(val) elif att == "R": # floating point val = float(val) transaction = 0 cfgData = [ (self._cfgval_keyname, val), ] except ValueError: valid_entry = False if valid_entry: msg = UBXMessage.config_set(layers, transaction, cfgData) self.__app.serial_handler.serial_write(msg.serialize()) self._ent_val.configure(bg=ENTCOL) self._lbl_send_command.config(image=self._img_pending) self.__container.set_status("CFG-VALSET SET message sent", "blue") self.__container.set_pending(UBX_CFGVAL, ("ACK-ACK", "ACK-NAK")) else: self._ent_val.configure(bg=ERRCOL) self._lbl_send_command.config(image=self._img_warn) typ = ATTDICT[att] self.__container.set_status( ("INVALID ENTRY - must conform to parameter " f"type {att} ({typ}) and size {atts} bytes"), "red", ) return valid_entry