目录

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+. The decoder needs only numpy and scipy.

Receiving live off an SDR additionally needs the SoapySDR bindings, which are a system package rather than a pip one — see Receive from an SDR.

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)

Receive from an SDR

Ready-to-run receivers for three common radios, in examples/:

python examples/sdr_live_rtl_sdr.py           # RTL-SDR
python examples/sdr_live_airspy_mini_sdr.py   # Airspy Mini
python examples/sdr_live_hackrf_sdr.py        # HackRF One
436.13125 MHz  sf=8  bw=125k  fs=3M /3 -> 1000k (8x)  gain=lna14/mix12/vga10  preamble=15

[16:03:26] t=  19.15s  snr=+11.2dB  cfo=     -9Hz
  len=11  cr=4/7  crc=off
  hex  68656c6c6f20776f726c64
  text 'hello world'

Each one tunes off-channel to dodge the radio’s DC spike, decimates to a rate the decoder likes, and folds each packet’s residual frequency error back into the software shift — so the receiver calibrates itself out of its own crystal error while it runs. --record keeps the IQ for offline replay.

These scripts need SoapySDR, which is not on PyPI:

sudo apt install soapysdr-tools python3-soapysdr
sudo apt install soapysdr-module-rtlsdr    # or -airspy, or -hackrf
python3 -m venv --system-site-packages .venv

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 receive off RTL-SDR / Airspy / HackRF examples/README.md
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.

关于

LibreCube(开源教育卫星与组件平台)开源仓库 python-softlora。镜像收录自 https://gitlab.com/librecube/lib/python-softlora,License:以源仓库 LICENSE 为准(MIT / CERN-OHL 等)

19.2 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号