LoRa Python Receiver & TinyGS Ground Station
Pure-Python LoRa PHY decoder (softlora) and an MQTT-connected TinyGS SDR ground station (tinygs)
A complete software LoRa ground station built during Google Summer of Code 2026 with LibreCube. It combines two pure-Python libraries into a single reception chain: softlora, a LoRa physical-layer decoder, and tinygs, an MQTT-connected ground station that reports decoded packets to the TinyGS network.
SoftLoRa — the LoRa Python Receiver
SoftLoRa is a pure-Python implementation of the LoRa physical layer, including. It depends only on numpy and scipy.
from softlora import LoRaDecoder
decoder = LoRaDecoder(sf=10, bw=125_000, fs=125_000, fc=437e6)
for packet in decoder.decode_file("recording.wav"):
print(packet.payload_text, packet.crc_valid)
The decoder was built for satellite downlinks, where signals are weak and Doppler-shifted. Synchronization follows the low-complexity 3-stage algorithm of Xhonneux et al. (2021), which estimates the Carrier Frequency Offset (CFO) and Symbol Timing Offset (STO) by exploiting the known chirp structure of the LoRa preamble.
Key capabilities:
- Recordings and live streams — decodes
.wav,.cfile,.dat, and.binfiles, as well as streaming IQ chunks as they arrive from an SDR. - Spreading factors 7–12 — configurable bandwidth, sample rate, and center frequency.
- Packet metadata — each
Packetexposes the payload bytes, UTF-8 text, CRC validity, and an SNR estimate, so you can filter forcrc_validpackets only. - Chase decoding — rescues weak packets by retrying marginal symbol decisions.
Performance — AWGN SNR Sweep
The receiver is validated with an end-to-end AWGN Monte Carlo testbench: a clean LoRa packet is generated with the gr-lora_sdr GNU Radio TX chain, then the same noisy draws are decoded, so only the sync + decode path is measured. Packet-error-rate curves sweep spreading factors 7 through 12.
Generating Packets with GNU Radio
Packets used for round-trip testing are produced by a gr-lora_sdr TX flowgraph, lora_TX.grc. A message strobe pushes a payload through the LoRa transmit chain and writes the resulting complex IQ to a .bin file.
TinyGS — the Ground Station
TinyGS is a Python ground station for the TinyGS satellite network, an unofficial reimplementation of the ESP32 TinyGS firmware. It handles the MQTT-TLS connection to mqtt.tinygs.com, receives satellite assignments, and publishes decoded packets to the server.
pip install tinygs # the station library + softlora decoder
pip install 'tinygs[sdr]' # the RTL-SDR Python backend
Running a station is three commands:
tinygs-create # answer some questions once -> station.json
tinygs-run # go live: connect, receive, report
tinygs-stop # go offline
The station is radio-agnostic: RtlSdrRadio is just an IQ source plus a decoder, so supporting a HackRF, a ZMQ stream, or a recorded file only means swapping the source. A simulator is included, so the whole pipeline can be exercised without hardware.
How They Connect
softlora ships as a dependency of tinygs. The station library supplies the IQ samples from the SDR; softlora turns those samples into packets; and the station library publishes the valid payloads back to the TinyGS network. Together they form a single, testable software ground station that runs on any Linux PC attached to an SDR and a band-tuned antenna.
Resources
Code & Documentation
- python-softlora — the LoRa PHY decoder (PyPI)
- python-tinygs — the ground station (PyPI)
Related Writing
Technologies Used
- Python 3.9+
- NumPy / SciPy
- SoapySDR + RTL-SDR
- MQTT-TLS
Developed as a Google Summer of Code 2026 project with LibreCube, an open source initiative for space and earth exploration systems.