This is a combination of my python coding practice, making python do things that I normally do in C, implementing a specification from a datasheet, and scratching a personal itch. It may be useful to others, so have at it!
The eventual goal is to support every released u-blox GPS receiver, but I only have a small selection to test with. Hardware donations of different u-blox GPS receivers are welcome. I currently have access to:
- MAX-M8Q
- SAM-M8Q
- MAX-7Q
PRs to make it suck less or implement more of the spec are welcome - especially implementing 9-series configuration.
I may eventually add support for talking to u-blox receivers over I2C or SPI, currently only serial (UART or USB) connections are supported.
Requires pyserial to talk interactively to a GPS receiver.
pip install pyserial
from ubx_cmd import UbxCmd
import serial
s = serial.Serial("COM6")
ubx = UbxCmd(s, read=True, write=True)
from ubx_cmd import UbxCmd
f = open("FILE", "wb")
ubx = UbxCmd(f, read=False, write=True)
from ubx_cmd import UbxCmd
import sys
ubx = UbxCmd(sys.stdin, read=True, write=False)
bytes = ubx_msg_poll(msgclass:int, msgid:int, data:bytes) = creates a UBX binary protocol message that polls the receiver for the given message class and message ID data. If the poll request message requires additional data, set the data bytes, otherwise the poll request message length is set to 0. Returns: bytes object of the poll response payload, excluding headers and checksum.
bool = ubx_msg_acknak(msgclass:int, msgid:int, data:bytes) = creates a UBX binary protocol message that expects a UBX-ACK-(N)ACK response (e.g. UBX-CFG commands). Returns: bool = True if UBX-ACK-ACK response received, False if UBX-ACK-NACK response received.
ubx_msg_send(msgclass:int, msgid:int, data:bytes) = creates a UBX binary protocol message of the given message class, message ID, and data. Generates the header and checksum, and sends the bytes to the stream.
transmit(data:bytes) = sends the data bytes to the stream exactly as passed.
queue.Queue = receive_queue_start(protocols:UbxMsg.INOUT_PROTOCOL|None, ubx_filters:[(msgclass, msgid, offset, data)], nmea_filters:[(sentence, strmatch)]) = received messages that match filters are inserted into the returned queue. protocols is a bitwise mask of protocols to match, if set to None then will match all protocols. ubx_filters is a list of tuples that will match the UBX binary protocol, with None in a filter tuple element meaning match anything. nmea_filters is a list of tuples that will match the NMEA protocol, with None in a filter tuple element meaning match anything. Queue messages will be exactly as received from the stream, including headers and checksums.
receive_queue_stop(queue:queue.Queue) = stop and delete the passed receive queue.
stream = an IO file handle that sends/receives bytes using read() and write() methods. Required - no default.
serial_baud = initial baud rate of the serial port - can be changed later using ubx_cfg_prt_uart(baud=int) but must be correct at init time when read=True. Most u-blox GPS receivers are set to 9600, however some newer receivers (e.g. NEO-M9N, MIA-M10Q) are set to 38400. Default: 9600
read and write = enable reading or writing of the stream respectively. Stream can only be read+write if it is a serial.Serial stream. Default: read=False and write=True
write_timeout = seconds to wait after sending a write command for a response from the receiver. Default: 1.0
protocol_version = manually-set protocol version, to ensure command compatibility. If the stream is read+write (i.e. a serial.Serial stream), the protocol version of the attached receiver will be probed and this parameter is ignored. Default: 18.00 (compatible with MAX-M8Q and SAM-M8Q)
log_level = specify a different logging log level for the module if necessary. Default: INFO
ubx_cfg_cfg_reset_all() = revert all configuration to defaults. Uses ubx_cfg_cfg internally.
ubx_cfg_cfg_save_all() = save current configuration to all configuration locations. Uses ubx_cfg_cfg internally.
ubx_cfg_cfg(data:bytes) = send a UBX-CFG-CFG message with the provided data bytes. Does not wait for a UBX-ACK-(N)ACK response as communication may be interrupted, instead it waits 0.5 seconds.
ubx_cfg_rst_hotstart() = hot-start the receiver immediately using internal watchdog. Uses ubx_cfg_rst internally.
ubx_cfg_rst_hotstart() = warm-start the receiver immediately using internal watchdog, discarding received ephemeresis data only. Uses ubx_cfg_rst internally.
ubx_cfg_rst_coldstart() = cold-start the receiver immediately using internal watchdog, discarding all received data. Uses ubx_cfg_rst internally.
ubx_cfg_rst(data:bytes) = send a UBX-CFG-RST message with the provided data bytes. Does not wait for a UBX-ACK-(N)ACK response as the hardware reset may happen before the response message is fully transmitted in older receivers, and newer receivers do not send a response at all, instead it waits 0.5 seconds.
ubx_cfg_gnss_enabled(gnss:list[UbxCmd.GNSS_ID_MAJOR|UbxCmd.GNSS_ID_AUGMENT], channels:int) = sets the enabled GNSS constellations to the list provided, and sets the maximum number of channels to use in the receiver. Refer to the u-blox Receiver Protocol Description for your receiver for the supported GNSS constellations, number of simultaneous GNSS supported, and constraints on enabling multiple GNSS simultaneously.
ubx_cfg_gnss_gps(enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int) = calls ubx_cfg_gnss_all(gnss=UbxCmd.GNSS_ID_MAJOR.GPS) and passes other arguments through.
ubx_cfg_gnss_glonass(enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int) = calls ubx_cfg_gnss_all(gnss=UbxCmd.GNSS_ID_MAJOR.GLONASS) and passes other arguments through.
ubx_cfg_gnss_galileo(enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int) = calls ubx_cfg_gnss_all(gnss=UbxCmd.GNSS_ID_MAJOR.Galileo) and passes other arguments through.
ubx_cfg_gnss_beidou(enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int) = calls ubx_cfg_gnss_all(gnss=UbxCmd.GNSS_ID_MAJOR.BeiDou) and passes other arguments through.
ubx_cfg_gnss_imes(enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int) = calls ubx_cfg_gnss_all(gnss=UbxCmd.GNSS_ID_AUGMENT.IMES) and passes other arguments through.
ubx_cfg_gnss_qzss(enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int) = calls ubx_cfg_gnss_all(gnss=UbxCmd.GNSS_ID_AUGMENT.QZSS) and passes other arguments through.
ubx_cfg_gnss_sbas(enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int, test_mode:bool, ranging:bool, correction:bool, integrity:bool, prn_mask:UbxCfg.SBAS_PRN) = calls ubx_cfg_gnss_all(gnss=UbxCmd.GNSS_ID_AUGMENT.SBAS) and passes other arguments through. Also configures SBAS settings.
ubx_cfg_gnss_all(gnss:GNSS_ID_MAJOR|GNSS_ID_AUGMENT, enabled:bool, min_channels:int, max_channels:int, sig_cfg_mask:int) = xxx
ubx_cfg_sbas(data:bytes) = xxx
ubx_cfg_msg(msgclass:int, msgid:int, ports=list[UbxCfg.PORT], rate:int) = set the receiver to automatically output the selected message class and message ID on the selected port(s) every rate seconds. If ports is an empty list, applies to all ports on the receiver. If rate is set to 0, disables the sending of the selected message. Refer to the u-blox Receiver Protocol Description for your receiver for valid message classes and IDs.
set_stream(stream:serial.Serial|io.BufferedIOBase) = change the IO stream to a new stream. Closes the old stream. If the new stream is a serial.Serial stream, it is configured with the current baud rate.
set_read(read:bool) = enable or disable reading of the stream. If the stream is not serial.Serial, writing will be disabled if reading is set to True
set_write(write:bool) = enable or disable writing of the stream. If the stream is not serial.Serial, reading will be disabled if writing is set to True
set_logging(level:logging._Level) = change the logging log level