SoftLoRa
Decode LoRa packets from radio recordings and live SDR streams, in pure Python.
Point it at an IQ recording and it finds the packets, corrects the frequency and
timing errors introduced by the radio link, and gives you back the payload.
No GNU Radio or C++ needed — just numpy and scipy.
It was built for satellite downlinks, where signals are weak and Doppler-shifted, and is tested on synthetic data, over-the-air captures and real satellite passes.
Developed for Google Summer of Code 2026 with LibreCube.
Install
pip install softlora
Python 3.9+.
Decode a recording
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 four arguments describe the signal you are decoding:
| Argument | Meaning |
|---|---|
sf |
Spreading factor, 7–12 |
bw |
LoRa bandwidth in Hz |
fs |
Sample rate of your recording in Hz |
fc |
Center frequency in Hz |
.wav, .cfile, .dat and .bin files are supported. A recording may hold
several packets, so you always get a list back.
Decode a live stream
Feed IQ chunks as they arrive from an SDR. Packets are returned as soon as they are complete, even when one spans two chunks:
decoder = LoRaDecoder(sf=10, bw=125_000, fs=250_000, fc=437e6)
while receiving:
for packet in decoder.decode_stream(read_iq_from_sdr(8192)):
print(packet.payload_text)
for packet in decoder.flush(): # decode whatever is left in the buffer
print(packet)
Reading the result
Every decode path returns Packet objects. The
fields you will usually want:
packet.payload_bytes # the data
packet.payload_text # the same data decoded as UTF-8
packet.crc_valid # True when the payload passed its checksum
packet.snr_est # signal-to-noise estimate in dB
packet.ok # a packet was found and demodulated
ok and crc_valid answer different questions. ok=True, crc_valid=False
means a packet arrived but was corrupted on the way. Filter on
packet.crc_valid is True when you only want trustworthy payloads.
A LoRa packet
Each packet starts with a preamble of plain upchirps, then a sync word, then a 2.25-symbol start-of-frame delimiter (SFD) made of downchirps, and finally the header, payload and CRC. All four regions are visible below.
| A real LoRa packet received from the Polytech Universe-3 (PU-3) satellite (SF8, 62.5 kHz bandwidth). The payload is truncated for display. |
Going further
| Topic | Where |
|---|---|
| Runnable examples | examples/ |
| Packets without a header | Quick start |
Tuning the decoder (DecoderSettings) |
The decode pipeline |
| Rescuing weak packets with Chase decoding | Chase guide |
| Live SDR chain via GNU Radio | examples/README.md |
| Doppler and carrier offset for satellites | Ground-station use |
| Benchmarks across SF 7–12 | Performance |
| How synchronization works | Sync algorithm |
| Full API reference | Documentation site |
References
[1] M. Xhonneux, O. Afisiadis, D. Bol, and J. Louveaux, "A Low-Complexity LoRa Synchronization Algorithm Robust to Sampling Time Offsets," IEEE Internet of Things Journal, 2021. arXiv:1912.11344
[2] J. Tapparel, O. Afisiadis, P. Mayoraz, A. Balatsoukas-Stimming, and A. Burg, "An Open-Source LoRa Physical Layer Prototype on GNU Radio," SPAWC, 2020.
License
MIT — see LICENSE and CONTRIBUTORS.txt.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file softlora-0.3.0.tar.gz.
File metadata
- Download URL: softlora-0.3.0.tar.gz
- Upload date:
- Size: 87.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07eb2023b34330a47e133457e0ac319fe1975abdd9309c37234983081371b260
|
|
| MD5 |
0f4975be7bcc4299bf441e0baddf85cc
|
|
| BLAKE2b-256 |
1caca8ab7a161a7d2382f53419898812ce385b8accf6d68d40fe7cfcfd767ed8
|
File details
Details for the file softlora-0.3.0-py3-none-any.whl.
File metadata
- Download URL: softlora-0.3.0-py3-none-any.whl
- Upload date:
- Size: 48.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a42c1533f05da94eded9c13270798f7e8932827316cc6c0a7178dc5038f9cffa
|
|
| MD5 |
c665ccf25c1405741778d56df61af25b
|
|
| BLAKE2b-256 |
1252959d2844279625c99abb6306a59ad964f5765ecd32e5dd5c297c26d96745
|