Skip to content

Commit

Permalink
update ubxbase
Browse files Browse the repository at this point in the history
  • Loading branch information
semuadmin committed Dec 6, 2024
1 parent 409f2b8 commit bec626a
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 56 deletions.
108 changes: 77 additions & 31 deletions src/pyubxutils/ubxbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
This command line utility configures an RTK-compatible u-blox
GNSS receiver to operate in Base Station mode.
RTCM 1006 (Antenna Reference Data) is only output if the base
station is active, so receipt of this message type is used as
a configuration success criterion.
Created on 06 Jan 2023
:author: semuadmin
Expand All @@ -21,6 +25,7 @@
from time import sleep

from pyubx2 import (
ERR_IGNORE,
NMEA_PROTOCOL,
RTCM3_PROTOCOL,
UBX_PROTOCOL,
Expand Down Expand Up @@ -63,14 +68,18 @@ def __init__(self, stream: object, **kwargs):
self.logger = getLogger(__name__)
self._stream = stream

self._port = kwargs["port"]
self._porttype = kwargs.get("porttype", "USB")
self._timemode = int(kwargs.get("timemode", TMODE_DISABLED))
self._acclimit = int(kwargs.get("acclimit", DEFAULT_ACCURACY))
self._duration = int(kwargs.get("duration", DEFAULT_DURATION))
self._postype = int(kwargs.get("postype", POS_LLH))
self._waittime = int(kwargs.get("waittime", WAITTIME))
self._fixedpos = kwargs.get("fixedpos", DEFAULT_POS)
self._ubxreader = UBXReader(
self._stream, protfilter=NMEA_PROTOCOL | UBX_PROTOCOL | RTCM3_PROTOCOL
self._stream,
protfilter=NMEA_PROTOCOL | UBX_PROTOCOL | RTCM3_PROTOCOL,
quitonerror=ERR_IGNORE,
)
self._out_queue = Queue()
self._stop_event = Event()
Expand All @@ -85,19 +94,20 @@ def __init__(self, stream: object, **kwargs):
self._stop_event,
),
)
self._svin_elapsed = 0
self._msg_ack = 0
self._msg_nak = 0
self._msg_write = 0
self._msg_load = 0 if self._timemode == TMODE_DISABLED else 1
self._msg_load = 0 # if self._timemode == TMODE_DISABLED else 1
self._msg_rtcm = 0

def _config_svin(self, queue: Queue, port_type: str = "USB") -> int:
def _config_svin(self, queue: Queue) -> int:
"""
Configure Survey-In mode with specified accuracy limit.
"""

print(
f"Survey-in duration {self._duration}s, accuracy limit {self._acclimit}cm ..."
f"Survey-in duration {self._duration}s, accuracy limit {self._acclimit}cm"
)
self._waittime += self._duration
layers = 1
Expand All @@ -107,7 +117,7 @@ def _config_svin(self, queue: Queue, port_type: str = "USB") -> int:
("CFG_TMODE_MODE", self._timemode),
("CFG_TMODE_SVIN_ACC_LIMIT", acclimit),
("CFG_TMODE_SVIN_MIN_DUR", self._duration),
(f"CFG_MSGOUT_UBX_NAV_SVIN_{port_type}", 1),
# (f"CFG_MSGOUT_UBX_NAV_SVIN_{port_type}", 1),
]
ubx = UBXMessage.config_set(layers, transaction, cfg_data)
queue.put(ubx)
Expand All @@ -121,7 +131,7 @@ def _config_fixed(self, queue: Queue) -> int:

print(
f"Fixed position format {('ECEF','LLH')[self._postype]}, {self._fixedpos}, "
f"accuracy limit {self._acclimit}cm ..."
f"accuracy limit {self._acclimit}cm"
)
layers = 1
transaction = 0
Expand Down Expand Up @@ -178,15 +188,21 @@ def _config_disabled(self, queue: Queue) -> int:
self._msg_load += 1
return 1

def config_rtcm(self, queue: Queue, rate: int = 1, port_type: str = "USB") -> int:
def _config_output(
self, queue: Queue, rate: int = 1, port_type: str = "USB"
) -> int:
"""
Configure which RTCM3 messages to output.
Configure which RTCM3 and UBX messages to output.
"""

print(f"{('Disabling','Enabling')[rate]} RTCM output messages ...")
print(f"{('Disabling','Enabling')[rate]} output messages")
layers = 1 # 1 = RAM, 2 = BBR, 4 = Flash (can be OR'd)
transaction = 0
cfg_data = []
cfg_data = (
[(f"CFG_MSGOUT_UBX_NAV_SVIN_{port_type}", 1)]
if self._timemode == TMODE_SVIN
else []
)
for rtcm_type in (
"1006",
"1077",
Expand All @@ -212,7 +228,7 @@ def _read_data(
):
"""
THREADED
Read incoming acknowledgements from device
Read incoming UBX and RTCM data from device.
"""
# pylint: disable=broad-except

Expand Down Expand Up @@ -243,6 +259,12 @@ def _read_data(
self.logger.debug(
f"RTCM 1006 ACTIVE BASE {self._msg_rtcm} - {parsed_data}"
)
if (
self._timemode == TMODE_SVIN
and parsed_data.identity == "NAV-SVIN"
):
self._svin_elapsed = parsed_data.dur
self.logger.debug(f"UBX NAV-SVIN - {parsed_data}")

# send config message(s) to receiver
if not queue.empty():
Expand Down Expand Up @@ -271,9 +293,13 @@ def run(self):
"""

rc = 0
print(
f"Configuring {('Disabled', 'Survey-In', 'Fixed')[self._timemode]} timing mode ..."
)
if self._timemode in (TMODE_FIXED, TMODE_SVIN):
print(
f"Configuring device at port {self._port} as base station using "
f"{('disabled', 'survey-in', 'fixed')[self._timemode]} timing mode"
)
else:
print(f"Configuring device at port {self._port} to disable base station")

start = datetime.now()
self._read_thread.start()
Expand All @@ -284,44 +310,56 @@ def run(self):
else:
rc = self._config_disabled(self._out_queue)
if rc:
rc = self.config_rtcm(self._out_queue, self._timemode != TMODE_DISABLED)
rc = self._config_output(
self._out_queue,
rate=self._timemode != TMODE_DISABLED,
port_type=self._porttype,
)

# loop until waittime expired or user presses Ctrl-C
# loop until waittime / survey duration expired or user presses Ctrl-C
i = 0
while datetime.now() < start + timedelta(seconds=self._waittime):
try:
progbar(i, self._waittime, min(self._waittime, 60))
i += 1
if self._timemode == TMODE_SVIN:
i = self._svin_elapsed # from NAV-SVIN message
wt = self._duration
else:
i += 1
wt = self._waittime
progbar(i, wt, wt)
sleep(1)
except KeyboardInterrupt: # capture Ctrl-C
print("Terminated by user. Configuration may be incomplete.")
print("\nTerminated by user. Configuration may be incomplete.")
break

self._stop_event.set()
self._read_thread.join()

if self._msg_ack + self._msg_rtcm >= self._msg_load:
if self._msg_ack == self._msg_load and (
(self._timemode in (TMODE_FIXED, TMODE_SVIN) and self._msg_rtcm > 1)
or (self._timemode == TMODE_DISABLED and self._msg_rtcm == 0)
):
print(
"Configuration successfully loaded. "
"Configuration successful. "
f"{self._msg_ack} configuration messages acknowledged. "
f"{self._msg_rtcm} RTCM 1006 (active base) message confirmed."
f"{self._msg_rtcm} RTCM 1006 (active base) messages confirmed."
)
rc = 1
else:
null = self._msg_load - self._msg_ack - self._msg_nak - self._msg_rtcm
rc = 0
print(
"\nConfiguration may be incomplete. "
"\nConfiguration unsuccessful. "
f"{self._msg_load} configuration messages sent, "
f"{self._msg_ack} acknowledged, {self._msg_nak} rejected, "
f"{self._msg_rtcm} RTCM 1006 (active base), {null} null responses."
f"{self._msg_rtcm} RTCM 1006 (active base) messages received."
)
if null:
if not self._msg_rtcm:
print(
f"Consider reducing accuracy limit to >{self._acclimit} cm"
f"or increasing waittime to >{self._waittime} seconds."
f"Consider increasing accuracy limit to >{self._acclimit}cm "
f"or increasing survey duration to >{self._duration} seconds."
)
if self._msg_nak:
print("Check device is compatible.")
print("Check device supports base station configuration.")
rc = 0

return rc

Expand Down Expand Up @@ -369,6 +407,14 @@ def fixedpos_in_range(value):
type=float,
default=3.0,
)
ap.add_argument(
"--portype",
required=False,
help="Serial port type",
type=str,
choices=("USB", "UART1", "UART2", "I2C"),
default="USB",
)
ap.add_argument(
"--timemode",
required=False,
Expand Down Expand Up @@ -421,7 +467,7 @@ def fixedpos_in_range(value):
kwargs = set_common_args("ubxload", ap, logdefault=VERBOSITY_HIGH)

with Serial(
kwargs.pop("port"), kwargs.pop("baudrate"), timeout=kwargs.pop("timeout")
kwargs.get("port"), kwargs.pop("baudrate"), timeout=kwargs.pop("timeout")
) as serial_stream:
ubl = UBXBase(serial_stream, **kwargs)
ubl.run()
Expand Down
8 changes: 4 additions & 4 deletions src/pyubxutils/ubxcompare.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def __init__(self, infiles: str, form: int = FORMAT_TXT, diffsonly: bool = True)
fcount += 1
self.parse_file(cfgdict, file.strip(), fcount, form)

self.logger.info(
print(
f"{fcount} files processed, list of {'differences in' if diffsonly else 'all'}"
" config keys and their values follows: ",
)
Expand All @@ -90,7 +90,7 @@ def __init__(self, infiles: str, form: int = FORMAT_TXT, diffsonly: bool = True)
if (diffsonly and diff) or not diffsonly:
print(f"{key} ({'DIFFS!' if diff else None}); {str(vals).strip('{}')}")

self.logger.info(f"Total config keys: {kcount}. Total differences: {dcount}.")
print(f"Total config keys: {kcount}. Total differences: {dcount}.")

def parse_line(self, line: str) -> UBXMessage:
"""
Expand Down Expand Up @@ -177,9 +177,9 @@ def parse_file(self, cfgdict: dict, filename: str, fileno: int, form: int):
self.get_attrs(cfgdict, str(parsed), fileno)
i += 1
except Exception as err:
self.logger.error(f"ERROR parsing {filename}! \n{err}")
print(f"ERROR parsing {filename}! \n{err}")

self.logger.info(f"\n{i} configuration commands processed in {filename}")
print(f"\n{i} configuration commands processed in {filename}")


def main():
Expand Down
18 changes: 6 additions & 12 deletions src/pyubxutils/ubxload.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def run(self):
"""

rc = 1
self.logger.info(
print(
f"Loading configuration from {self._filename} to {self._stream.port}. "
"Press Ctrl-C to terminate early.",
)
Expand All @@ -182,35 +182,29 @@ def run(self):
try:
sleep(1)
except KeyboardInterrupt: # capture Ctrl-C
self.logger.warning(
"Terminated by user. Configuration may be incomplete."
)
print("Terminated by user. Configuration may be incomplete.")
self._stop_event.set()

self._read_thread.join()

if self._msg_ack == self._msg_load:
self.logger.info(
print(
"Configuration successfully loaded. "
f"{self._msg_load} CFG-VALSET messages sent and acknowledged."
)
else:
null = self._msg_load - self._msg_ack - self._msg_nak
rc = 0
self.logger.warning(
print(
"Configuration may be incomplete. "
f"{self._msg_load} CFG-VALSET messages sent, "
f"{self._msg_ack} acknowledged, {self._msg_nak} rejected, "
f"{null} null responses."
)
if null:
self.logger.warning(
f"Consider increasing waittime to >{self._waittime} seconds."
)
print(f"Consider increasing waittime to >{self._waittime} seconds.")
if self._msg_nak:
self.logger.warning(
"Check device is compatible with this saved configuration."
)
print("Check device is compatible with this saved configuration.")

return rc

Expand Down
8 changes: 4 additions & 4 deletions src/pyubxutils/ubxsave.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def run(self):
"""

rc = 1
self.logger.info(
print(
f"Saving configuration from {self._stream.port} to {self._file.name}. "
"Press Ctrl-C to terminate early."
)
Expand Down Expand Up @@ -242,16 +242,16 @@ def run(self):

except KeyboardInterrupt: # capture Ctrl-C
self._stop_event.set()
self.logger.warning("Terminated by user. Configuration may be incomplete.")
print("Terminated by user. Configuration may be incomplete.")

if self._msg_rcvd == self._cfgkeys:
self.logger.info(
print(
"Configuration successfully saved. "
f"{self._msg_save} CFG-VALSET messages saved to {self._file.name}"
)
else:
rc = 0
self.logger.warning(
print(
"Configuration may not be successfully saved. "
f"{self._msg_sent} CFG-VALGET polls sent to {self._stream.port}, "
f"{self._msg_rcvd} CFG-VALGET responses received, "
Expand Down
8 changes: 3 additions & 5 deletions src/pyubxutils/ubxsetrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,7 @@ def apply(self):
"""

try:
self.logger.info(
f"Opening serial port {self._port} @ {self._baudrate} baud ..."
)
print(f"Opening serial port {self._port} @ {self._baudrate} baud ...")
self._serialOut = Serial(self._port, self._baudrate, timeout=self._timeout)

if self._msgClass == ALLNMEA: # all available NMEA messages
Expand Down Expand Up @@ -142,7 +140,7 @@ def apply(self):
raise err from err
finally:
if self._serialOut is not None:
self.logger.info("Configuration message(s) sent.")
print("Configuration message(s) sent.")
self._serialOut.close()

def _sendmsg(self, msgClass: int, msgID: int):
Expand All @@ -166,7 +164,7 @@ def _sendmsg(self, msgClass: int, msgID: int):
rateSPI=self._rate,
)

self.logger.info(f"Sending configuration message {msg}...")
print(f"Sending configuration message {msg}...")
self._serialOut.write(msg.serialize())


Expand Down

0 comments on commit bec626a

Please sign in to comment.