Пример #1
0
    def _do_attributes(self, **kwargs):
        """Populate UBXMessage from named attribute keywords.
        Where a named attribute is absent, set to a nominal value (zeros or blanks).

        :param **kwargs:

        """

        offset = 0

        try:

            if len(kwargs) == 0:  # if no kwargs, assume null payload
                self._payload = None
            else:
                pdict = self._get_dict()  # get appropriate payload dict
                for key in pdict.keys():  # set each attribute in dict
                    (offset,
                     att) = self._set_attribute(offset, pdict, key, **kwargs)
            self._do_len_checksum()

        except (AttributeError, OverflowError, struct.error, TypeError,
                ValueError) as err:
            raise ube.UBXTypeError((f"Incorrect type for attribute '{key}' "
                                    f"in {self.mode2str(self._mode)} message "
                                    f"class {self.identity}")) from err
        except ube.UBXTypeError as err:
            raise ube.UBXTypeError((f"Undefined attribute type '{att}' "
                                    f"in {self.mode2str(self._mode)} message "
                                    f"class {self.identity}")) from err
        except KeyError as err:
            raise ube.UBXMessageError(
                (f"Undefined {self.mode2str(self._mode)} "
                 f"message class={self._ubxClass}, "
                 f"id={self._ubxID}")) from err
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
    def _do_attributes(self, **kwargs):
        """
        Populate UBXMessage from named attribute keywords.
        Where a named attribute is absent, set to a nominal value (zeros or blanks).

        :param kwargs: optional payload key/value pairs
        :raises: UBXTypeError

        """

        offset = 0  # payload offset in bytes
        index = []  # array of (nested) group indices

        try:

            if len(kwargs) == 0:  # if no kwargs, assume null payload
                self._payload = None
            else:
                self._payload = kwargs.get("payload", b"")
                pdict = self._get_dict(**
                                       kwargs)  # get appropriate payload dict
                for key in pdict:  # process each attribute in dict
                    (offset,
                     index) = self._set_attribute(offset, pdict, key, index,
                                                  **kwargs)
            self._do_len_checksum()

        except (
                AttributeError,
                struct.error,
                TypeError,
                ValueError,
        ) as err:
            raise ube.UBXTypeError(
                (f"Incorrect type for attribute '{key}' "
                 f"in {['GET', 'SET', 'POLL'][self._mode]} message "
                 f"class {self.identity}")) from err
        except (OverflowError, ) as err:
            raise ube.UBXTypeError(
                (f"Overflow error for attribute '{key}' "
                 f"in {['GET', 'SET', 'POLL'][self._mode]} message "
                 f"class {self.identity}")) from err
Пример #5
0
    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
Пример #6
0
    def _set_attribute(self, offset: int, pdict: dict, key: str,
                       **kwargs) -> (int, str):
        """Recursive routine to populate individual payload attributes

        :param offset: int:
        :param pdict: dict:
        :param key: str:
        :param **kwargs:

        """
        # pylint: disable=no-member

        #  if repeating group, suffix keyword with index
        if self._index > 0:
            keyr = key + "_{0:0=2d}".format(self._index)
        else:
            keyr = key

        att = pdict[key]  # get attribute type
        if isinstance(
                att,
                tuple):  # attribute is a tuple i.e. a nested repeating group
            numr, attd = att
            if numr == "None":
                rng = self._calc_num_repeats(attd, self._payload, offset)
            else:
                rng = getattr(self, numr)
            for i in range(rng):
                self._index = i + 1
                for key1 in attd.keys():
                    (offset, _) = self._set_attribute(offset, attd, key1,
                                                      **kwargs)

        else:

            if att == ubt.CH:  # INF message payload
                atts = len(self._payload)
            else:
                atts = int(att[1:3])

            # if the entire payload has been provided,
            # use the appropriate section of the payload
            if "payload" in kwargs:
                self._payload = kwargs["payload"]
                val = self._payload[offset:offset + atts]
                if (
                        att == ubt.CH
                ):  # attribute is a single variable-length string (e.g. INF-NOTICE)
                    val = self._payload.decode("utf-8", "backslashreplace")
                elif att[0:1] in ("X", "C"):
                    pass
                elif att[0:1] == "U":  # unsigned integer
                    val = int.from_bytes(val, "little", signed=False)
                elif att[0:1] == "I":  # signed integer
                    val = int.from_bytes(val, "little", signed=True)
                elif att == ubt.R4:  # single precision floating point
                    val = self.bytes_to_float(val)
                elif att == ubt.R8:  # double precision floating point
                    val = self.bytes_to_double(val)
                else:
                    raise ube.UBXTypeError(
                        f"Unknown attribute type {att} for key {key}")

            # else if individual attribute has been provided
            elif keyr in kwargs:
                val = kwargs[keyr]
                if att[0:1] in ("X", "C"):  # byte or char
                    valb = val
                elif att[0:1] == "U":  # unsigned integer
                    valb = val.to_bytes(atts, byteorder="little", signed=False)
                elif att[0:1] == "I":  # signed integer
                    valb = val.to_bytes(atts, byteorder="little", signed=True)
                elif att == ubt.R4:  # single precision floating point
                    valb = self.float_to_bytes(val)
                elif att == ubt.R8:  # double precision floating point
                    valb = self.double_to_bytes(val)
                else:
                    raise ube.UBXTypeError(
                        f"Unknown attribute type {att} for key {key}")
                self._payload += valb

            # else set individual attribute to nominal value
            else:
                if att[0:1] in ("X", "C"):  # byte or char
                    valb = b"\x00" * atts
                    val = valb
                elif att[0:1] == "U":  # unsigned integer
                    val = 0
                    valb = val.to_bytes(atts, byteorder="little", signed=False)
                elif att[0:1] == "I":  # signed integer
                    val = 0
                    valb = val.to_bytes(atts, byteorder="little", signed=True)
                elif att == ubt.R4:  # single precision floating point
                    val = 0.0
                    valb = self.float_to_bytes(val)
                elif att == ubt.R8:  # double precision floating point
                    val = 0.0
                    valb = self.double_to_bytes(val)
                else:
                    raise ube.UBXTypeError(
                        f"Unknown attribute type {att} for key {key}")
                self._payload += valb

        if not isinstance(att, tuple):
            if self._index > 0:  # add 2-digit suffix to repeating attribute names
                key = key + "_{0:0=2d}".format(self._index)
            setattr(self, key, val)
            offset += atts

        return (offset, att)