Leon Steenkamp
Building small satellites on the tip of Africa. My other ride is a CubeSat.
Open water swim tracker - tracker embedded software
This post is part of the series detailing the Open water swim tracker project - more info here.
This section gives more detail on the software that runs on the tracker hardware. The tracker hardware is placed on the boat that accompanies the swimmer and periodically sends GPS data over its LTE link to the project server.
Software components/technologies:
- Python
- Bash script
- Cron jobs
- gpsd
- systemd
- Ansible
- Mosh
- Tailscale
- Git
Most of the software functionality is implemented using Python scripts. Python was used as it allowed features to be implemented and tested quickly, and using existing libraries reduced the implementation time.
The software on the tracker has to run mostly unattended and be able to recover from most issues by itself. It is possible to connect to the tracker remotely using Tailscale and using Mosh makes this a painless experience. Connecting to the tracker remotely is only possible when the tracker is able to connect to the Internet.
When the Alcatel USB LTE modem is plugged into the RPi, it appears as a network interface, and the modem hosts a webpage with connection-related information. This page was reverse-engineered to find the information needed to directly query the information from the API presented by the modem.
The parsing of data from the GPS receiver is done by the gpsd (a GPS service daemon) package. Clients connect to the service using the Python gps library to retrieve GPS information.
The main function of the tracker is implemented by a Python script that reads the GPS information from gpsd and writes it to the API provided by the project web application. The project web application is described in more detail in another post. The script reads and timestamps the position information (latitude and longitude) and writes it to the web app application. Position data is currently logged every 60 seconds.
A Python library was created to retrieve information from the USB LTE modem connected to the RPi. This library is used by both the InfluxDB logging and OLED screen scripts.
Logging operational data to a remote host is implemented as another Python script, which allows remote monitoring of the tracker operation. This Python script gathers and writes data to a remote InfluxDB instance. This data is then visualised using Grafana running on the same remote host. The InfluxDB and Grafana instances run on remote Raspberry Pi (RPi) on my local LAN (this will be covered further in the next post). Data that is logged relates to the operation of the GPS receiver (number of satellites, fix mode, speed, altitude and position) and LTE modem (signal information, connection status and data used). Other telemetry can easily be added to the logging in the future.
The I2C interface on the RPi is enabled to allow interfacing to the small OLED screen. This screen cycles through various pages with GPS and connection information. The OLED Python script gathers its information independently of the other scripts running on the device.
![]() |
---|
The tracker hardware inside enclosure |
The three Python scripts (for InfluxDB, OLED and web app) used on the tracker are operated as systemd services. And are configured to start at boot and restart if they stop.
Some work configuration changes were made to have the RPi favour a WiFi connection, if available, over the LTE connection. This was done by adjusting the route metrics for each interface, but also by adjusting the routing table to add a routing rule for source-based routing. In cases where the LTE modem might not have a good connection, a WiFi hotspot could be created by another device (using another service provider) for the RPi to connect to and use.
Two cron jobs are installed on the RPi. The first is a quick fix that periodically restarts gpsd. It was noticed that the gpsd service became unresponsive occasionally, and restarting the service seems to solve the issue. The cause still has to be investigated, but if the problem does not persist when switching to a GPS with a serial UART connection rather than the current USB GPS, then the fix is no longer needed.
The second cron job runs a bash script to check the LTE modem and connection. It has been observed that sometimes the modem is in the wrong mode or its interface is not assigned an IP address. It is possible for the LTE modem to be either storage or modem mode. Occasionally, the modem is in the wrong mode at boot or its interface is not assigned an IP, and the script will change the mode to modem or reset the modem using the usb_modeswitch command.
The current software and configuration have performed well in real-world testing so far. Testing of the tracker and embedded software will be covered further in an upcoming post.
After initial configuration and testing of the software, the process was automated using Ansible. This also serves as documentation for the software installation and configuration process. An Ansible playbook can now be used to easily and quickly install and configure the needed software for the swim tracker on another RPi. This is useful as there is a non-zero chance that the tracker hardware can be lost or damaged while in use. The project software is kept under version control using Git.
Other posts in the series
- Open water swim tracker - project overview - Link
- Tracker hardware - Link
- Tracker embedded software - Link
- Software for internal monitoring and logging - Coming soon
- End user web application - Coming soon
- Other hardware options and future developments - Coming soon
- Open water swim tracker testing - Coming soon
- End goal tracker - Coming soon