diff --git a/.vscode/settings.json b/.vscode/settings.json index 4a46f3b..5d877a9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,5 @@ "python.defaultInterpreterPath": "python3", "modulename": "${workspaceFolderBasename}", "distname": "${workspaceFolderBasename}", - "moduleversion": "1.1.7" + "moduleversion": "1.1.8" } \ No newline at end of file diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 9b945b3..49b05b0 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,11 @@ # pygnssutils Release Notes +### RELEASE 1.1.8 + +ENHANCEMENTS: + +1. gnssmqttclient updated to support `pyspartn>=1.0.5` (see [pyspartn Release Notes](https://github.com/semuconsulting/pyspartn/blob/main/RELEASE_NOTES.md) for new functionality). + ### RELEASE 1.1.7 ENHANCEMENTS: diff --git a/pyproject.toml b/pyproject.toml index 8e35ebd..7714397 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "pygnssutils" authors = [{ name = "semuadmin", email = "semuadmin@semuconsulting.com" }] maintainers = [{ name = "semuadmin", email = "semuadmin@semuconsulting.com" }] description = "GNSS Command Line Utilities" -version = "1.1.7" +version = "1.1.8" license = { file = "LICENSE" } readme = "README.md" requires-python = ">=3.9" @@ -37,7 +37,7 @@ dependencies = [ "certifi>=2024.0.0", "paho-mqtt>=1.6.0", # waiting for >=2.0.0 in Conda "pyserial>=3.5", - "pyspartn>=1.0.4", + "pyspartn>=1.0.5", "pyubx2>=1.2.48", ] diff --git a/src/pygnssutils/_version.py b/src/pygnssutils/_version.py index ea5621a..349da3f 100644 --- a/src/pygnssutils/_version.py +++ b/src/pygnssutils/_version.py @@ -8,4 +8,4 @@ :license: BSD 3-Clause """ -__version__ = "1.1.7" +__version__ = "1.1.8" diff --git a/src/pygnssutils/gnssmqttclient.py b/src/pygnssutils/gnssmqttclient.py index 63a8dce..8476404 100644 --- a/src/pygnssutils/gnssmqttclient.py +++ b/src/pygnssutils/gnssmqttclient.py @@ -30,7 +30,6 @@ # pylint: disable=invalid-name import socket -from datetime import datetime, timezone from io import BufferedWriter, BytesIO, TextIOWrapper from logging import getLogger from os import getenv, path @@ -42,6 +41,8 @@ import paho.mqtt.client as mqtt from paho.mqtt import __version__ as PAHO_MQTT_VERSION from pyspartn import ( + ERRLOG, + SPARTNDecryptionError, SPARTNMessageError, SPARTNParseError, SPARTNReader, @@ -62,12 +63,16 @@ TOPIC_DATA, TOPIC_FREQ, TOPIC_KEY, + VERBOSITY_MEDIUM, ) +from pygnssutils.helpers import set_logging from pygnssutils.mqttmessage import MQTTMessage TIMEOUT = 8 DLGTSPARTN = "SPARTN Configuration" +_global_timetags = {} # for want of a better approach + class GNSSMQTTClient: """ @@ -83,7 +88,10 @@ def __init__(self, app=None, **kwargs): self.__app = app # Reference to calling application class (if applicable) # configure logger with name "pygnssutils" in calling module + verbosity = int(kwargs.pop("verbosity", VERBOSITY_MEDIUM)) + logtofile = kwargs.pop("logtofile", "") self.logger = getLogger(__name__) + set_logging(getLogger("pyspartn"), verbosity, logtofile) self._validargs = True clientid = getenv(ENV_MQTT_CLIENTID, default="enter-client-id") @@ -106,7 +114,7 @@ def __init__(self, app=None, **kwargs): ), "spartndecode": 0, "spartnkey": getenv(ENV_MQTT_KEY, default=None), - "spartnbasedate": datetime.now(timezone.utc), + "spartnbasedate": None, "output": None, } @@ -368,6 +376,7 @@ def on_message(client, userdata, msg): # pylint: disable=unused-argument :param object msg: SPARTN or UBX message topic content """ + global _global_timetags output = userdata["output"] app = userdata["app"] msglogger = userdata["logger"] @@ -418,12 +427,24 @@ def do_write(raw: bytes, parsed: object): decode=userdata["decode"], key=userdata["key"], basedate=userdata["basedate"], + timetags=_global_timetags, + quitonerror=ERRLOG, ) try: for raw, parsed in spr: do_write(raw, parsed) - except (SPARTNMessageError, SPARTNParseError, SPARTNStreamError): - parsed = f"MQTT SPARTNParseError {msg.topic} {msg.payload}" + _global_timetags = spr.timetags + except ( + SPARTNMessageError, + SPARTNParseError, + SPARTNStreamError, + ) as err: + msglogger.error(err) + parsed = f"{msg.topic} {err}" + do_write(msg.payload, parsed) + except SPARTNDecryptionError as err: + msglogger.error(err) + parsed = f"{msg.topic} {err}" do_write(msg.payload, parsed) @staticmethod diff --git a/src/pygnssutils/gnssmqttclient_cli.py b/src/pygnssutils/gnssmqttclient_cli.py index 6fd7859..e8e4a58 100644 --- a/src/pygnssutils/gnssmqttclient_cli.py +++ b/src/pygnssutils/gnssmqttclient_cli.py @@ -11,7 +11,6 @@ """ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser -from datetime import datetime, timezone from os import getenv, path from pathlib import Path from queue import Queue @@ -167,8 +166,13 @@ def main(): ap.add_argument( "--spartnbasedate", required=False, - help="Decryption basedate for encrypted payloads", - default=datetime.now(timezone.utc), + help=( + "Decryption basedate for encrypted payloads (-1 = current datetime, " + "0 = use timetags from data stream, " + "other integer = 32-bit gnssTimeTag value)" + ), + type=int, + default=-1, ) ap.add_argument( "--waittime", @@ -211,6 +215,9 @@ def main(): ) kwargs = set_common_args("gnssmqttclient", ap) + if kwargs.get("spartnbasedate", 0) == -1: + kwargs["spartnbasedate"] = None # will default to current datetime in pyspartn + kwargs["errevent"] = Event() cliout = int(kwargs.pop("clioutput", OUTPUT_NONE)) try: diff --git a/src/pygnssutils/gnssntripclient.py b/src/pygnssutils/gnssntripclient.py index 9324160..796fc7d 100644 --- a/src/pygnssutils/gnssntripclient.py +++ b/src/pygnssutils/gnssntripclient.py @@ -63,8 +63,9 @@ NTRIP2, NTRIP_EVENT, OUTPORT_NTRIP, + VERBOSITY_MEDIUM, ) -from pygnssutils.helpers import find_mp_distance, ipprot2int +from pygnssutils.helpers import find_mp_distance, ipprot2int, set_logging from pygnssutils.socketwrapper import SocketWrapper TIMEOUT = 3 @@ -100,7 +101,11 @@ def __init__( self.__app = app # Reference to calling application class (if applicable) # configure logger with name "pygnssutils" in calling module + self.verbosity = int(kwargs.pop("verbosity", VERBOSITY_MEDIUM)) + self.logtofile = kwargs.pop("logtofile", "") self.logger = getLogger(__name__) + for module in ("pyrtcm", "pyspartn"): + set_logging(getLogger(module), self.verbosity, self.logtofile) self._ntripqueue = Queue() # initialise and persist settings to allow any calling app to retrieve them self._settings = {}