A small python code to remotely reset GNSS receivers of ZED-F9P and HD9310

category: gnss
tags: f9p hd9310 rtk rtklib

Certain messages (e.g. pseudoranges) may not be output during long-term remote observation with a u-blox ZED-F9P receiver or Allystar HD9310 (TAU1302) receiver。

In such cases, restarting the connected microcomputer will often fix the problem. However, in such cases, sending a reset command to the GNSS receiver chip may also fix it. If it is a u-blox chipset, you can send the reset command to the chipset with the dedicated software u-center, but here I will send the reset command with Python code.

It is assumed that these receivers are connected to the USB port of the microcomputer Raspberry Pi 3, and that they can be remotely controlled with the bidirectional option -b of the RTKLIB CUI application str2str.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Reference Documents:
#   R1: u-blox F9P HPG 1.30 Interface Description
#   R2: Allystar GNSS Receiver Protocol Specification V2.3

import socket
import sys

host = 'Host name or IP address of the microcomputer Raspberry Pi'

def send_cmd(port, preamble, command, payload):
    pllen = len(payload).to_bytes(2, 'little') # payload length in bytes
    csum1, csum2 = rtk_checksum (command + pllen + payload)
    csum = csum1.to_bytes(1, 'little') + csum2.to_bytes(1, 'little')
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.send(preamble + command + pllen + payload + csum)

def rtk_checksum(payload):
    checksum1 = 0
    checksum2 = 0
    for b in payload:
        checksum1 += b
        checksum2 += checksum1
        checksum1 &= 0xff
        checksum2 &= 0xff
    return checksum1, checksum2

if __name__ == '__main__':
    if sys.argv[1] == 'f9p':
        port = Port number of microcomputer to which F9P is connected
        preamble = b'\xb5\x62' # preamble 0xb5 0x62, ref R1, p.53
        command  = b'\x06\x04' # UBX-CFG-RST, ref R1, p.86
        payload  = b'\x00\x00' # hot start
        payload += b'\x00'     # hardware reset immediately
        payload += b'\x00'     # reserved
        print ('warning: you may need restarting str2str')
    elif sys.argv[1] == 'hd9310':
        port = Port number of the microcomputer to which the HD9310 is connected
        preamble = b'\xf1\xd9' # preamble, ref R2, p.21
        command = b'\x06\x40'  # CFG-SIMPLERST, ref R2, p.56
        payload = b'\x01'      # reset
    else:
        print ('Err: arg should be either f9p or hd9310')
        sys.exit()

    send_cmd(port, preamble, command, payload)

# EOF

We save this code with a file name such as gnss_reset.py, and add the execution attribute with chmod 755 gnss_reset.py.

Then we can remotely reset the receiver by running ./gnss_reset.py f9p or ./gnss_reset.py hd9310.

Both u-blox receivers and Allystar receivers are supposed to send preambles, commands, data, and checksums for reception, and both use the same checksum generation method, so a part of the code could be shared. For u-blox receivers, we may need restarting str2str running on the microcomputer after this reset.