CQta - IP-over-radio tunneling with QSO features
CQta is a cross-platform (Windows, Linux, macOS) tunneling app that routes IPv4 over a Meshtastic radio connected via BLE, AFSK audio modem or an existing KISS TNC.
It creates a network interface with a real IP address, through which a real IP subnet is routed. This is obtained by using pytap3 package.
Some basic IPv4 filtering blocks IGMP, SSDP/mDNS and other OS chatter.
It also contains an implementation of a basic, human-readable UDP protocol called CQta, designed for this app and whose canonical protocol specification is also maintained here. It is fun for testing that the link works, having QSOs over the link without additional software and small TFTP file transfers. It interoperates with the mobile CQta apps. Of course, the real usefulness is in using your existing IP applications over the tunnel. But be aware that TCP is a very chatty protocol and, at its default settings, not really efficient for radio; UDP stuff will work better.
Four ways to reach the radio network:
| Transport | Details |
|---|---|
| Meshtastic | USB serial, Bluetooth LE or TCP |
| AFSK sound modem | 1200 baud Bell-202 style AFSK over a sound card |
| KISS TCP TNC | Raw IPv4 in KISS frames over an already running TCP KISS TNC such as Dire Wolf |
| Network interface | Plain UDP over an already configured OS interface. Useful if the underlying interface is already radio, like with HSMM links or similar devices |
Privileges
CQta runs as a regular user. Chat, ping and file transfer build and parse IP packets inside the app and need no special rights. Only if you tick System network interface is a small helper process started with elevated rights to create the TUN/TAP device through pytap3; the GUI itself never runs elevated.
Run the GUI application
pip install cqta
cqta # or: python -m cqta
Starting the tunnel interface from command line (no GUI)
cqta --tunnel runs headless and keeps an OS tunnel up until Ctrl+C / SIGTERM,
then tears it down. It never asks for administrator rights: start it as root
(sudo cqta --tunnel) or from an elevated terminal on Windows, otherwise it
says so and exits with an error.
It is useful for headless systems and for when you want to bring up the tunnel automatically via systemd and similar.
Use cqta --help to see the full syntax; here are some examples.
sudo cqta --tunnel # the connection used last in the GUI
sudo cqta --tunnel --meshtastic-serial /dev/ttyUSB0
sudo cqta --tunnel --meshtastic-ble # value left out: strongest Bluetooth node
sudo cqta --tunnel 44.130.1.5/16 --kiss 127.0.0.1:8001/0
sudo cqta --tunnel 10.115.4.7/16 --afsk --input-device "USB Audio Device" --output-device "USB Audio Device" --beacon-interval 120 --callsign MYCALL
cqta --list serial|ble|audio|interfaces # discover device names
cqta --dump-config # print the command line equivalent to the GUI's current connection
cqta --help # every option, with ranges and defaults
An useful workflow would be to use the GUI to configure your transport, check
that it works, then use --dump-config to see the command line you have to use
to run exactly like that in an automated script.
The beacon is useful even if you don't use the GUI, because it will send out an UDP packet containing your cleartext callsign every interval, thus satisfying ham radio laws periodic identification requirements.
Tests
pip install -e .[dev]
pytest
Packaged builds
pip install -e .[build]
python packaging/build.py
Produces dist/cqta-<version>-<platform>-<architecture> as a single-file .exe
(Windows), .AppImage (Linux, needs appimagetool and docker) or a signed
.app in a .dmg (macOS).
-
Linux: the PyInstaller step runs in a
manylinux_2_28docker container, so the AppImage needs glibc 2.28 or newer (e.g. Debian 10, Ubuntu 18.10, RHEL 8).CQTA_NO_CONTAINER=1builds against the host instead. PySide6 only publishes x86_64 wheels for this baseline. -
macOS: the build makes its own venv from python.org's Python 3.13 (
CQTA_MACOS_PYTHONoverrides the path) with only wheels built for macOS 12 or older, so the app runs on macOS 12+; the build fails if any bundled binary needs something newer. The app is signed with the first of:CQTA_CODESIGN_IDENTITY, a Developer ID Application certificate, another valid certificate (Apple Development / personal team), a self-signed certificate, or an ad-hoc signature. With a Developer ID Application certificate the app and dmg are also notarized and stapled so Gatekeeper accepts them. Credentials come fromAPPLE_ID+APPLE_TEAM_ID+APPLE_APP_PASSWORD, or from anotarytoolkeychain profile (xcrun notarytool store-credentials app-notary;CQTA_NOTARY_PROFILEselects another name). With no Developer ID certificate or no credentials the build still succeeds, unnotarized. -
Windows: the executable runs on Windows 10 or better, and already bundles all required DLLs.
Metadata
Release files for cqta 2.1.post1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cqta-2.1.post1.tar.gz | 903.8 kB | Without provenance | Details for cqta-2.1.post1.tar.gz |
Release files / cqta-2.1.post1.tar.gz
| Download URL | cqta-2.1.post1.tar.gz |
|---|---|
| Size | 903.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
15b8c5ff55811970207caab676459a30010871b61690cc440c32ae4c64a4b6d1
|
|
BLAKE2b-256 checksum How to use checksums |
f88edc70d23cce1fede07897310fb0b53443d990d9af1b771a5affe5db0a9053
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.17
|
Security for cqta 2.1.post1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.