pyspartn package

Submodules

pyspartn.exceptions module

SPARTN Custom Exception Types

Created on 10 Feb 2023

author:

semuadmin

copyright:

SEMU Consulting © 2023

license:

BSD 3-Clause

exception pyspartn.exceptions.ParameterError[source]

Bases: Exception

Parameter Error Class.

exception pyspartn.exceptions.SPARTNParseError[source]

Bases: Exception

SPARTN Parsing error.

exception pyspartn.exceptions.SPARTNDecryptionError[source]

Bases: Exception

SPARTN Decryption error.

exception pyspartn.exceptions.SPARTNStreamError[source]

Bases: Exception

SPATRTN Streaming error.

exception pyspartn.exceptions.SPARTNMessageError[source]

Bases: Exception

SPARTNUndefined message class/id. Essentially a prompt to add missing payload types to SPARTN_MGSIDS.

exception pyspartn.exceptions.SPARTNTypeError[source]

Bases: Exception

SPARTN Undefined payload attribute type.

pyspartn.socket_wrapper module

socket_wrapper.py

A skeleton socket wrapper which provides basic stream-like read(bytes) and readline() methods.

NB: this will read from a socket indefinitely. It is the responsibility of the calling application to monitor data returned and implement appropriate socket error, timeout or inactivity procedures.

Created on 4 Apr 2022

author:

semuadmin

copyright:

SEMU Consulting © 2022

license:

BSD 3-Clause

class pyspartn.socket_wrapper.SocketWrapper(sock: socket, **kwargs)[source]

Bases: object

socket stream class.

__init__(sock: socket, **kwargs)[source]

Constructor.

Parameters:
  • socket (sock) – socket object

  • bufsize (int) – (kwarg) internal buffer size (4096)

property buffer: bytearray

Getter for buffer.

Returns:

buffer

Return type:

bytearray

read(num: int) bytes[source]

Read specified number of bytes from buffer. NB: always check length of return data.

Parameters:

num (int) – number of bytes to read

Returns:

bytes read (which may be less than num)

Return type:

bytes

pyspartn.spartnhelpers module

Collection of SPARTN helper methods which can be used outside the SPARTNMessage or SPARTNReader classes

Created on 10 Feb 2023

author:

semuadmin

copyright:

SEMU Consulting © 2023

license:

BSD 3-Clause

pyspartn.spartnhelpers.att2idx(att: str) int[source]

Get integer index corresponding to grouped attribute. e.g. SF019_04 -> 4; SF019_23 -> 23

Parameters:

att (str) – grouped attribute name e.g. SF019_01

Returns:

index as integer, or 0 if not grouped

Return type:

int

pyspartn.spartnhelpers.att2name(att: str) str[source]

Get name of grouped attribute. e.g. SF019 -> SF019; SF019_23 -> SF019

Parameters:

att (str) – grouped attribute name e.g. SF019_06

Returns:

name without index e.g. SF019

Return type:

str

pyspartn.spartnhelpers.datadesc(datafield: str) str[source]

Get description of data field.

Parameters:

datafield (str) – datafield e.g. ‘SF054’

Returns:

datafield description e.g. “Ionosphere equation type”

Return type:

str

pyspartn.spartnhelpers.bitsval(bitfield: bytes, position: int, length: int, typ: str = 'IN', res: float = 1.0, rngmin: float = 0.0) int[source]

Get unisgned integer value of masked bits in bytes.

Parameters:
  • bitfield (bytes) – bytes

  • position (int) – position in bitfield, from leftmost bit

  • length (int) – length of field in bits

  • typ (str) – field type (i.e. Integer, Bitmask, Float)

  • res (float) – field resolution (i.e. scaling factor)

  • rngmin (float) – field range minimum value

Returns:

value

Return type:

int

Raises:

SPARTNMessageError if end of bitfield

pyspartn.spartnhelpers.crc_poly(data: int, n: int, poly: int, crc: int = 0, ref_out: bool = False, xor_out: int = 0) int[source]

Configurable CRC algorithm.

Parameters:
  • data (int) – data

  • n (int) – width

  • poly (int) – polynomial feed value

  • crc (int) – crc

  • ref_out – reflection out

  • xor_out – XOR out

Returns:

CRC

Return type:

int

pyspartn.spartnhelpers.valid_crc(msg: bytes, crc: int, crctype: int) bool[source]

Validate message CRC.

Parameters:
  • msg (bytes) – message to which CRC applies

  • crc (int) – message CRC

  • cycType (int) – crc type (0-3)

pyspartn.spartnhelpers.encrypt(pt: bytes, key: bytes, iv: bytes, mode: str = 'CTR') tuple[source]

Encrypt payload The length of the plaintext data must be a multiple of the cipher block length (16 bytes), so padding bytes are added as necessary.

Parameters:
  • data (bytes) – plaintext data

  • key (bytes) – key

  • iv (bytes) – initialisation vector

  • mode (str) – cipher mode e.g. CTR, CBC

Returns:

tuple of (encrypted data, number of padding bytes)

Return type:

tuple

pyspartn.spartnhelpers.decrypt(ct: bytes, key: bytes, iv: bytes, mode: str = 'CTR') bytes[source]

Decrypt payload

Parameters:
  • ct (bytes) – encrypted data (ciphertext)

  • key (bytes) – key

  • iv (bytes) – initialisation vector

  • mode (str) – cipher mode e.g. CTR, CBC

Returns:

decrypted data (plaintext)

Return type:

bytes

pyspartn.spartnhelpers.escapeall(val: bytes) str[source]

Escape all byte characters e.g. b’\x73’ rather than b`s`

Parameters:

val (bytes) – bytes

Returns:

string of escaped bytes

Return type:

str

pyspartn.spartnhelpers.timetag2date(timetag32: int) datetime[source]

Convert 32-bit gnsstimetag to datetime.

Parameters:

timetag (int) – 32-bit gnsstimetag

Returns:

date

Return type:

datetime

pyspartn.spartnhelpers.date2timetag(date: datetime) int[source]

Convert datetime to 32-bit gnsstimetag.

Parameters:

date (datetime) – date

Returns:

32-bit gnssTimeTag

Return type:

int

pyspartn.spartnhelpers.convert_timetag(timetag16: int, basedate: datetime = datetime.datetime(2024, 11, 20, 8, 28, 45, 772860, tzinfo=datetime.timezone.utc)) int[source]

Convert 16-bit timetag to 32-bit format.

32-bit timetag represents total seconds since 2010-01-01 00:00:00 (TIMEBASE).

16-bit timetag represents seconds past ‘base date’ (the datetime the SPARTN message was originally sent, to the nearest half-day). It requires knowledge of this base date to convert unambiguously to a 32-bit timetag equivalent, e.g.

If base date to nearest half day was “2023-06-27 12:00:00”, a timetag16 of 32580 represents a datetime of:

(2023-06-27 00:00:00 + 12 hours + 32580 seconds) = 2023-06-27 21:03:00

To convert to a 32-bit timetag, calculate number of seconds since TIMEBASE:

(2023-06-27 21:03:00 - 2010-01-01 00:00:00) = 425595780 seconds

All timetag16 are given in their respective constellation timezone : UTC = GPS + 18s = GAL + 18s = QZSS + 18s = BEI + 4s = GLO - 10800s

Since all timetags are in GNSS constellation time and basedate is UTC, we calculate three possible 32-bit timetags : basedate, basedate plus half a day, basedate minus half a day, so all constellations and basedate time reference are tried. We then select the unambiguous resolution the closest in time to the original basedate.

Parameters:
  • timetag16 (int) – 16-bit gnssTimeTag

  • basedate (datetime) – original processing datetime accurate to 3 hours

Returns:

32-bit gnssTimeTag

Return type:

int

pyspartn.spartnhelpers.naive2aware(dt: datetime, tz: timezone = datetime.timezone.utc) datetime[source]

Convert naive datetime to aware.

Parameters:
  • dt (datetime) – datetime

  • tz (timezone) – timezone (utc)

Returns:

datetime object with UTC timezone

Return type:

datetime

pyspartn.spartnhelpers.enc2float(value: int, res: float, rngmin: float = 0) float[source]

Convert encoded floating point value to float.

SPARTN protocol stores floating point numbers in encoded integer format.

Parameters:
  • value (int) – encoded value

  • res (float) – resolution

  • rngmin (float) – minimum range value

Returns:

floating point value

Return type:

float

pyspartn.spartnmessage module

SPARTNMessage class.

The MQTT key, required for payload decryption, can be passed as a keyword or set up as environment variable MQTTKEY.

Created on 10 Feb 2023

author:

semuadmin

copyright:

SEMU Consulting © 2023

license:

BSD 3-Clause

class pyspartn.spartnmessage.SPARTNMessage(transport: bytes = None, validate: int = 1, decode: bool = False, key: str = 'abcd1234abcd1234abcd1234abcd1234', basedate: object = None, timetags: dict = None)[source]

Bases: object

SPARTNMessage class.

__init__(transport: bytes = None, validate: int = 1, decode: bool = False, key: str = 'abcd1234abcd1234abcd1234abcd1234', basedate: object = None, timetags: dict = None)[source]

Constructor.

Parameters:
  • transport (bytes) – SPARTN message transport (None)

  • validate (bool) – validate CRC (True)

  • decode (bool) – decrypt and decode payloads (False)

  • key (str) – decryption key as hexadecimal string (Nominal)

  • basedate (object) – decryption basedate as datetime or 32-bit gnssTimeTag as integer (None). If basedate = TIMEBASE, timetags argument will be used

  • timetags (dict) – dict of decryption timetags in format {0: 442626332, 1: 449347321, 2: 412947745} where key = msgSubtype (0=GPS, 1=GLO, etc) and value = gnssTimeTag (None)

Raises:

ParameterError if invalid parameters

Raises:

SPARTNDecryptionError if unable to decrypt message using key and basedate/timetags provided

Raises:

SPARTNMessageError if transport, payload or CRC invalid

serialize() bytes[source]

Serialize message.

Returns:

serialized output

Return type:

bytes

property identity: str

Return message identity.

Returns:

message identity e.g. “SPARTN_1X_OCB_GPS”

Return type:

str

property payload: bytes

Return payload.

Returns:

payload

Return type:

bytes

pyspartn.spartnreader module

SPARTNReader class.

The SPARTNReader class will parse individual SPARTN messages from any binary stream containing solely SPARTN data e.g. an MQTT /pp/ip topic.

Information sourced from https://www.spartnformat.org/download/ (available in the public domain) © 2021 u-blox AG. All rights reserved.

SPARTN 1X transport layer bit format:

preamble

framestart

payload descriptor

payload

embedded auth data

crc

8 bits 0x73 ‘s’

24 bits

32-64 bits

8-8192 bits

0-512 bits

8-32 bits

NB Use of gnssTimeTag for message decryption:

The SPARTN protocol requires a key and basedate to calculate the Initialisation Vector (IV) for encrypted messages (eaf=1). The key is provided by the SPARTN service provider. The basedate is derived in one of two ways:

  1. For messages with unambiguous 32-bit gnssTimeTag values (timeTagtype = 1), the basedate is the gnssTimeTag. No other information is needed.

  2. For messages with ambiguous 16-bit gnssTimeTag values (timeTagtype = 0), the basedate can be derived from a 32-bit gnssTimeTag for the same message subtype (GPS, GLO, etc.) from the same datastream, or provided as an external parameter. SPARTNReader will accumulate any 32-bit gnssTimeTag in the incoming datastream for use in decryption.

Created on 10 Feb 2023

author:

semuadmin

copyright:

SEMU Consulting © 2023

license:

BSD 3-Clause

class pyspartn.spartnreader.SPARTNReader(datastream, validate: int = 1, quitonerror: int = 1, decode: bool = False, key: str = None, basedate: object = None, bufsize: int = 4096, errorhandler: object = None, timetags: dict = None)[source]

Bases: object

SPARTNReader class.

__init__(datastream, validate: int = 1, quitonerror: int = 1, decode: bool = False, key: str = None, basedate: object = None, bufsize: int = 4096, errorhandler: object = None, timetags: dict = None)[source]

Constructor.

Parameters:
  • stream (datastream) – input data stream

  • validate (int) – VALCRC (1) = validate CRC, VALNONE (1) = ignore invalid CRC (1)

  • quitonerror (int) – ERROR_IGNORE (0) = ignore, ERROR_LOG (1) = log and continue, ERROR_RAISE (2) = (re)raise (1)

  • decode (bool) – decrypt and decode payload (False)

  • key (str) – decryption key as hexadecimal string (None)

  • basedate (object) – decryption basedate as datetime or 32-bit gnssTimeTag as integer (None). If basedate = TIMEBASE, SPARTNMessage will use timetags argument

  • bufsize (int) – socket recv buffer size (4096)

  • errorhandler (int) – error handling object or function (None)

  • timetags (dict) – dict of decryption timetags in format {0: 442626332, 1: 449347321, 2: 412947745} where key = msgSubtype (0=GPS, 1=GLO, etc) and value = gnssTimeTag (None)

Raises:

ParameterError if invalid parameters

Raises:

SPARTNDecryptionError if unable to decrypt message using key and basedate/timetags provided

Raises:

SPARTN***Error if unable to parse message

read() tuple[source]

Read a single SPARTN message from the stream buffer and return both raw and parsed data.

The ‘quitonerror’ flag determines whether to raise, log or ignore parsing errors. If error and quitonerror = 1, the ‘parsed’ value will contain the error message.

Returns:

tuple of (raw_data as bytes, parsed_data as SPARTNMessage)

Return type:

tuple

Raises:

SPARTN***Error if error during parsing

property datastream: object

Getter for stream.

Returns:

data stream

Return type:

object

property timetags: dict

Getter for accumulated 32-bit gnssTimeTag time tags from data stream.

Can be used as a source of decryption basedate for each msgSubtype (i.e. GNSS constellation) if no other basedate is supplied.

Returns:

dict of gnssTimeTag from data stream (key is msgSubtype)

Return type:

dict

static parse(message: bytes, validate: int = 1, decode: bool = False, key: str = None, basedate: object = None, timetags: dict = None) SPARTNMessage[source]

Parse SPARTN message to SPARTNMessage object.

Parameters:
  • message (bytes) – SPARTN raw message bytes

  • validate (int) – 0 = ignore invalid CRC, 1 = validate CRC (1)

  • decode (int) – decode payload True/False

  • key (str) – decryption key (required if decode = 1)

  • basedate (object) – basedate as datetime or 32-bit gnssTimeTag as integer (None)

  • timetags (dict) – dict of accumulated gnssTimeTags from data stream (None)

Returns:

SPARTNMessage object

Return type:

SPARTNMessage

Raises:

SPARTN…Error (if data stream contains invalid data or unknown message type)

pyspartn.spartntables module

SPARTN Bitmask, Lookup and Decode Constants

Created on 10 Feb 2023

Information Sourced from https://www.spartnformat.org/download/ (available in the public domain) © 2021 u-blox AG. All rights reserved.

author:

semuadmin

pyspartn.spartntables.SATBITMASKKEY = {'BEI': 'SF094', 'GAL': 'SF093', 'GLO': 'SF012', 'GPS': 'SF011', 'QZS': 'SF095'}

Satellite PRN bitmask keys

pyspartn.spartntables.SATIODEKEY = {'BEI': 'SF100', 'GAL': 'SF099', 'GLO': 'SF019', 'GPS': 'SF018', 'QZS': 'SF101'}

Satellite IODE keys

pyspartn.spartntables.SF011_ENUM = {0: 32, 1: 44, 2: 56, 3: 64}

GPS satellite mask length (leftmost 2 bits of SF011)

pyspartn.spartntables.SF012_ENUM = {0: 24, 1: 36, 2: 48, 3: 63}

GLONASS satellite mask length (leftmost 2 bits of SF012)

pyspartn.spartntables.SF093_ENUM = {0: 36, 1: 45, 2: 54, 3: 64}

Galileo satellite mask length (leftmost 2 bits of SF093)

pyspartn.spartntables.SF094_ENUM = {0: 37, 1: 46, 2: 55, 3: 64}

BDS satellite mask length (leftmost 2 bits of SF094)

pyspartn.spartntables.SF095_ENUM = {0: 10, 1: 40, 2: 48, 3: 64}

QZSS satellite mask length (leftmost 2 bits of SF095)

pyspartn.spartntables.SATBITMASKLEN = {'SF011': [32, 44, 56, 64], 'SF012': [24, 36, 48, 63], 'SF093': [36, 45, 54, 64], 'SF094': [37, 46, 55, 64], 'SF095': [10, 40, 48, 64]}

Satellite PRN bitmask lengths (PRN values are bitmask position + 1)

pyspartn.spartntables.PBBITMASKKEY = {'BEI': 'SF103', 'GAL': 'SF102', 'GLO': 'SF026', 'GPS': 'SF025', 'QZS': 'SF104'}

Phase bias bitmask keys

pyspartn.spartntables.PBBITMASKLEN = {'SF025': ([6, 11], {0: 'L1C', 1: 'L2W', 2: 'L2L', 3: 'L5Q'}), 'SF026': ([5, 9], {0: 'L1C', 1: 'L2C'}), 'SF102': ([8, 15], {0: 'L1C', 1: 'L5Q', 2: 'L7Q'}), 'SF103': ([8, 15], {0: 'L2I', 1: 'L5P', 2: 'L7I', 3: 'L6I', 4: 'L1P', 5: 'L7P', 6: 'L8P'}), 'SF104': ([6, 11], {0: 'L1C', 1: 'L2L', 2: 'L5Q'})}

Phase bias bitmask lengths and enumerations

pyspartn.spartntables.CBBITMASKKEY = {'BEI': 'SF106', 'GAL': 'SF105', 'GLO': 'SF028', 'GPS': 'SF027', 'QZS': 'SF107'}

Code bias bitmask keys

pyspartn.spartntables.CBBITMASKLEN = {'SF027': ([6, 11], {0: 'C1C', 1: 'C2W', 2: 'C2L', 3: 'C5Q'}), 'SF028': ([5, 9], {0: 'C1C', 1: 'C2C'}), 'SF105': ([8, 15], {0: 'C1C', 1: 'C5Q', 2: 'C7Q'}), 'SF106': ([8, 15], {0: 'C2I', 1: 'C5P', 2: 'C7I', 3: 'C6I', 4: 'C1P', 5: 'C7P', 6: 'C8P'}), 'SF107': ([6, 11], {0: 'C1C', 1: 'C2L', 2: 'C5Q'})}

Code bias bitmask lengths and enumerations

pyspartn.spartntables.ALN_ENUM = {0: 8, 1: 12, 2: 16, 3: 32, 4: 64}

Embedded authorisation length enumeration

pyspartn.spartntables.SF015_ENUM = {0: '0 secs', 1: '1 secs', 2: '5 secs', 3: '10 secs', 4: '30 secs', 5: '60 secs', 6: '120 secs', 7: '320 secs'}

Continuity indicator enumeration

pyspartn.spartntables.SF024_ENUM = {0: 'unknown', 1: '0.01 m', 2: '0.02 m', 3: '0.05 m', 4: '0.1 m', 5: '0.3 m', 6: '1.0 m', 7: '> 1.0 m'}

User range error (URE) enumeration

pyspartn.spartntables.SF042_ENUM = {0: 'unknown', 1: '<= 0.010 m', 2: '<= 0.020 m', 3: '<= 0.040 m', 4: '<= 0.080 m', 5: '<= 0.160 m', 6: '<= 0.320 m', 7: '> 0.320 m'}

Troposphere quality enumeration

pyspartn.spartntables.SF044_ENUM = {0: 'Troposphere small coefficient block', 1: 'Troposphere large coefficient block'}

Troposphere polynomial coefficient size indicator

pyspartn.spartntables.SF051_ENUM = {0: 'Troposphere small residual', 1: 'Tropospherelarge residual'}

Troposphere residual field size

pyspartn.spartntables.SF055_ENUM = {0: 'Unknown', 1: '<= 0.03 TECU', 2: '<= 0.05 TECU', 3: '<= 0.07 TECU', 4: '<= 0.14 TECU', 5: '<= 0.28 TECU', 6: '<= 0.56 TECU', 7: '<= 1.12 TECU', 8: '<= 2.24 TECU', 9: '<= 4.48 TECU', 10: '<= 8.96 TECU', 11: '<= 17.92 TECU', 12: '<= 35.84 TECU', 13: '<= 71.68 TECU', 14: '<= 143.36 TECU', 15: '> 143.36 TECU'}

Ionosphere quality enumeration

pyspartn.spartntables.SF056_ENUM = {0: 'Ionosphere small coefficient block', 1: 'Ionosphere large coefficient block'}

Ionosphere polynomial coefficient size indicator

pyspartn.spartntables.SF063_ENUM = {0: 'Ionosphere small residual', 1: 'Ionosphere medium residual', 2: 'Ionosphere large residual', 3: 'Ionosphere extra large residual'}

Ionosphere residual field size enumeration

pyspartn.spartntables.SF070_ENUM = {0: '350 km', 1: '400 km', 2: '450 km', 3: '500 km'}

Ionosphere shell height enumeration

pyspartn.spartntables.SF077_ENUM = {0: '2.5 deg', 1: '5.0 deg', 2: '10.0 deg', 3: '15.0 deg'}

BPAC area latitude/longitude grid node spacing enumeration

pyspartn.spartntables.SF081_ENUM = {0: 'small VTEC residual', 1: 'large VTEC residual'}

VTEC size indicator

pyspartn.spartntables.SF085_ENUM = {0: 'AES', 1: 'ChaCha12', 2: 'ChaCha20'}

Encryption Type enumeration

pyspartn.spartntables.SF087_ENUM = {0: 96, 1: 128, 2: 192, 3: 256, 4: 512}

Key length enumeration

pyspartn.spartntables.SF090_ENUM = {0: 'none', 1: 'Ed25519', 2: 'SHA-2', 3: 'SHA-3'}

Group Authentication Type enumeration

pyspartn.spartntables.SF091_ENUM = {0: 32, 1: 64, 2: 96, 3: 128, 4: 192, 5: 256, 6: 512}

Computed Authentication Data (CAD) Length enumeration

pyspartn.spartntables.SF096_ENUM = {0: 'Galileo F/NAV', 1: 'Galileo I/NAV', 2: 'Galileo C/NAV'}

Galileo ephemeris type

pyspartn.spartntables.SF097_ENUM = {0: 'D1 Nav (B1I)', 1: 'D2 Nav (B1I)', 2: 'D1 Nav (B3I)', 3: 'D2 Nav (B3I)', 4: 'B-CNAV1', 5: 'B-CNAV2'}

BDS ephemeris type

pyspartn.spartntables.SF098_ENUM = {0: 'LNAV (L1C/A)', 1: 'CNAV2 (L1C)', 2: 'CNAV (L2C,L5)'}

QZSS ephemeris type

pyspartn.spartntypes_core module

SPARTN Protocol core globals and constants

Created on 10 Feb 2023

Information Sourced from https://www.spartnformat.org/download/ (available in the public domain) © 2021 u-blox AG. All rights reserved.

author:

semuadmin

copyright:

SEMU Consulting © 2023

license:

BSD 3-Clause

pyspartn.spartntypes_core.TIMEBASE = datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)

Initial epoch for SPARTN protocol.

pyspartn.spartntypes_core.DEFAULTKEY = 'abcd1234abcd1234abcd1234abcd1234'

Nominal 32-char hex key.

pyspartn.spartntypes_core.ERRRAISE = 2

(Re)raise errors

pyspartn.spartntypes_core.ERRLOG = 1

Log errors and continue

pyspartn.spartntypes_core.ERRIGNORE = 0

Ignore errors

pyspartn.spartntypes_core.VALNONE = 0

No validation of CRC or Message ID

pyspartn.spartntypes_core.VALCRC = 1

Valildate CRC checksum

pyspartn.spartntypes_core.VALMSGID = 2

Validate Message ID

pyspartn.spartntypes_core.SPARTN_PREB = b's'

SPARTN preamble byte

pyspartn.spartntypes_get module

SPARTN Protocol core globals and constants

Created on 10 Feb 2023

Information Sourced from https://www.spartnformat.org/download/ (available in the public domain) © 2021 u-blox AG. All rights reserved.

Payload definitions are contained in a series of dictionaries. Repeating and conditional elements are defined as a tuple of (element size/presence designator, element dictionary). The element size/presence designator can take one of the following forms:

Repeating elements:
  • an integer representing the fixed size of the repeating element N.

  • a string representing the name of a preceding attribute containing the size of the repeating element N (note that in some cases the attribute represents N - 1) e.g.

"group": (  # repeating group * (SF030 + 1)
    "SF030",
    {
        "SF031": "Area ID",
        etc ...
    },
)
Conditional elements:
  • a tuple containing a string and either a single value or a list of values, representing the name of a preceding attribute and the value(s) it must take in order for the optional element to be present e.g.

"optSF041-12": (
    ("SF041+1", [1, 2]),  # if SF041I in 1,2
    {
        "SF055": "Ionosphere quality",
        etc ...
    }
)

An ‘NB’ prefix indicates that the element size is given by the number of set bits in the attribute, rather than its integer value e.g. ‘NB + “SF011”’ -> if SF011 = 0b0101101, the size of the repeating element is 4.

A ‘+1’ or ‘+2’ suffix indicates that the attribute name must be suffixed with the specified number of nested element indices e.g. ‘SF041+1’ -> ‘SF041_01’

In some instances, the size of the repeating element must be derived from multiple attributes. In these cases the element size is denoted by a composite attribute name which is calculated within spartnmessage.py e.g. ‘PBBMLEN’

author:

semuadmin

copyright:

SEMU Consulting © 2023

license:

BSD 3-Clause

Module contents

Created on 10 Feb 2023

author:

semuadmin

copyright:

SEMU Consulting © 2023

license:

BSD 3-Clause