Skip to content

Commit

Permalink
Merge pull request #27 from semuconsulting/RC-1.0.1
Browse files Browse the repository at this point in the history
Rc 1.0.1
  • Loading branch information
semuadmin authored Jun 4, 2024
2 parents 6f0ce8a + 789fd94 commit 31b4a76
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 199 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"python3.8InterpreterPath": "/Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8",
"modulename": "${workspaceFolderBasename}",
"distname": "${workspaceFolderBasename}",
"moduleversion": "1.0.0"
"moduleversion": "1.0.1"
}
6 changes: 6 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

ENHANCEMENTS:

1. Internal enhancements to logging and exception handling.

### RELEASE 1.0.0

ENHANCEMENTS:

1. Add payload attributes for PRN, Phase Bias and Code Bias values, derived from the corresponding bitmasks for each constellation type. e.g. `PRN_01=3`, `PhaseBias_01_03=L2L`, `CodeBias_02_03=C2L`.
1. Add examples `parse_ocb.py` & `parse_hpac.py` illustrating how to convert parsed and decoded OCB and HPAC messages into iterable data structures.
1. Add `naive2aware(dt,tz)` helper method - convert naive basedates to aware with UTC timezone.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "pyspartn"
authors = [{ name = "semuadmin", email = "[email protected]" }]
maintainers = [{ name = "semuadmin", email = "[email protected]" }]
description = "SPARTN protocol parser"
version = "1.0.0"
version = "1.0.1"
license = { file = "LICENSE" }
readme = "README.md"
requires-python = ">=3.8"
Expand Down
2 changes: 1 addition & 1 deletion src/pyspartn/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
:license: BSD 3-Clause
"""

__version__ = "1.0.0"
__version__ = "1.0.1"
17 changes: 10 additions & 7 deletions src/pyspartn/spartnhelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ def att2idx(att: str) -> int:
"""

try:
return int(att[att.rindex("_") - len(att) + 1 :])
att = att.split("_")
ln = len(att)
if ln == 2: # one group level
return int(att[1])
if ln > 2: # nested group level(s)
return tuple(int(att[i]) for i in range(1, ln))
return 0 # not grouped
except ValueError:
return 0

Expand All @@ -43,10 +49,7 @@ def att2name(att: str) -> str:
:rtype: str
"""

try:
return att[: att.rindex("_")]
except ValueError:
return att
return att.split("_")[0]


def datadesc(datafield: str) -> str:
Expand Down Expand Up @@ -91,8 +94,8 @@ def bitsval(
f"Attribute size {length} exceeds remaining payload length {lbb - position}"
)

intval = (
int.from_bytes(bitfield, "big") >> (lbb - position - length) & 2**length - 1
intval = int.from_bytes(bitfield, "big") >> (lbb - position - length) & (
(1 << length) - 1
)
if typ == FL: # float
return enc2float(intval, res, rngmin)
Expand Down
19 changes: 11 additions & 8 deletions src/pyspartn/spartnmessage.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ def _do_attributes(self):
anam = ""
try:
if self._decode:
self._paylenb = len(self._payload) * 8 # payload length in bits
self._payloadi = int.from_bytes(self._payload, "big") # payload as int
pdict = (
self._get_dict()
) # get payload definition dict for this message identity
Expand Down Expand Up @@ -362,8 +364,8 @@ def _set_attribute_single(
# get value of required number of bits at current payload offset
# (attribute length, resolution, minimum, description)
attinfo = SPARTN_DATA_FIELDS[anam]
attlen = attinfo[0]
atttyp = attinfo[1] # IN, EN, BM, FL
atttyp = attinfo[0] # IN, EN, BM, FL
attlen = attinfo[1]
if isinstance(attlen, str): # variable length attribute
attlen = self._getvarlen(anam, index)
try:
Expand All @@ -373,14 +375,15 @@ def _set_attribute_single(
val = self._pbsmap[index[-1] - 1]
elif atttyp == CBS:
val = self._cbsmap[index[-1] - 1]
elif atttyp == FL:
res = attinfo[2] # resolution (i.e. scaling factor)
rngmin = attinfo[3] # range minimum
val = bitsval(self._payload, offset, attlen, atttyp, res, rngmin)
else:
val = bitsval(self._payload, offset, attlen, atttyp)
# inline for performance...
# fmt: off
val = self._payloadi >> (self._paylenb - offset - attlen) & ((1 << attlen) - 1)
# fmt: on
if atttyp == FL:
val = (val * attinfo[2]) + attinfo[3] # (val * res) + rngmin

except SPARTNMessageError as err:
# print(self)
raise err

setattr(self, anami, val)
Expand Down
29 changes: 19 additions & 10 deletions src/pyspartn/spartnreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@
# pylint: disable=invalid-name too-many-instance-attributes

from datetime import datetime, timezone
from logging import getLogger
from os import getenv
from socket import socket

from pyspartn.exceptions import (
ParameterError,
SPARTNMessageError,
SPARTNParseError,
SPARTNStreamError,
SPARTNTypeError,
)
from pyspartn.socket_stream import SocketStream
Expand Down Expand Up @@ -77,8 +79,9 @@ def __init__(
"""Constructor.
:param datastream stream: input data stream
:param int validate: 0 = ignore invalid CRC, 1 = validate CRC (1)
:param int quitonerror: 0 = ignore, 1 = log and continue, 2 = (re)raise (1)
:param int validate: VALCRC (1) = validate CRC, VALNONE (1) = ignore invalid CRC (1)
:param int quitonerror: ERROR_IGNORE (0) = ignore, ERROR_LOG (1) = log and continue,
ERROR_RAISE (2) = (re)raise (1)
:param bool decode: decrypt and decode payload (False)
:param str key: decryption key as hexadecimal string (None)
:param object basedate: basedate as datetime or 32-bit gnssTimeTag as integer (now)
Expand All @@ -96,6 +99,7 @@ def __init__(
self._validate = validate
self._quitonerror = quitonerror
self._errorhandler = errorhandler
self._logger = getLogger(__name__)
self._decode = decode
self._key = key
# accumlated array of 32-bit gnssTimeTag from datastream
Expand Down Expand Up @@ -160,8 +164,8 @@ def read(self) -> tuple:
return (None, None)
except (SPARTNParseError, SPARTNMessageError, SPARTNTypeError) as err:
if self._quitonerror:
self._do_error(str(err))
parsed_data = str(err)
self._do_error(err)
continue

return (raw_data, parsed_data)

Expand Down Expand Up @@ -251,24 +255,29 @@ def _read_bytes(self, size: int) -> bytes:
"""

data = self._stream.read(size)
if len(data) < size: # EOF
if len(data) == 0: # EOF
raise EOFError()
if 0 < len(data) < size: # truncated stream
raise SPARTNStreamError(
"Serial stream terminated unexpectedly. "
f"{size} bytes requested, {len(data)} bytes returned."
)
return data

def _do_error(self, err: str):
def _do_error(self, err: Exception):
"""
Handle error.
:param str err: error message
:raises: SPARTNParseError if quitonerror = 2
:param Exception err: error message
:raises: Exception if quitonerror = 2
"""

if self._quitonerror == ERRRAISE:
raise SPARTNParseError(err)
raise err from err
if self._quitonerror == ERRLOG:
# pass to error handler if there is one
if self._errorhandler is None:
print(err)
self._logger.error(err)
else:
self._errorhandler(err)

Expand Down
Loading

0 comments on commit 31b4a76

Please sign in to comment.