Skip to main content

SoftLoRa

Google Summer of Code 2026

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

softlora-0.3.0.tar.gz (87.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

softlora-0.3.0-py3-none-any.whl (48.7 kB view details)

Uploaded Python 3

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

Hashes for softlora-0.3.0.tar.gz
Algorithm Hash digest
SHA256 07eb2023b34330a47e133457e0ac319fe1975abdd9309c37234983081371b260
MD5 0f4975be7bcc4299bf441e0baddf85cc
BLAKE2b-256 1caca8ab7a161a7d2382f53419898812ce385b8accf6d68d40fe7cfcfd767ed8

See more details on using hashes here.

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

Hashes for softlora-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a42c1533f05da94eded9c13270798f7e8932827316cc6c0a7178dc5038f9cffa
MD5 c665ccf25c1405741778d56df61af25b
BLAKE2b-256 1252959d2844279625c99abb6306a59ad964f5765ecd32e5dd5c297c26d96745

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page