Skip to content

Repository files navigation

SWLer

A clean, receive-only web interface for shortwave listening. SWLer has a verified Icom IC-7300 setup and can also sit alongside an existing, working Hamlib rigctld for other radios. Phones and desktop browsers on your LAN or Tailscale network become simple listening terminals.

SWLer scan interface on desktop and mobile

The screenshot is an illustrative layout reference. Station names and schedules in it are not reception claims.

SWLer is built for listening, not for recreating every front-panel control in a browser. There is no transmit path, waterfall, recording, account system, or cloud service.

What it does

  • Tunes saved stations and streams the radio's USB receive audio
  • Groups a broadcaster's frequencies under one station
  • Shows broadcasts that are on air, up next, or worth watching
  • Scans known catalog channels in sequence with pause, step, dwell, and loop
  • Scans whole categories on demand, such as Pirates or International
  • Saves reusable Scan Sets on the server
  • Discovers the safe receive features offered by the connected Hamlib backend
  • Provides filters, gain, noise controls, and a signal meter when the radio reports that it supports them
  • Stores your stations, notes, tags, schedules, and hidden records in SQLite
  • Refreshes EiBi schedules only when you ask it to
  • Offers three compact themes, each with light and dark appearances

One receiver is shared by every connected browser. The latest manual tune wins; scan controls are shared too.

Before you start

SWLer currently targets Ubuntu 26.04 and Python 3.14. The included radio service is specifically for the IC-7300. Other radios are welcome when they already work through a local, normal-mode Hamlib rigctld; SWLer does not configure those radios for you.

It also needs:

  • Hamlib's rigctld
  • FFmpeg with PulseAudio input and MP3 encoding
  • PipeWire/PulseAudio tools (pactl)
  • SQLite's command-line tool for the documented backup command

On Ubuntu:

sudo apt install libhamlib-utils ffmpeg pulseaudio-utils sqlite3

The web app binds to 0.0.0.0:8073 by default and has no authentication or built-in HTTPS. Use it only on a trusted LAN or Tailscale network.

Install

git clone https://github.com/b3p3k0/SWLer.git
cd SWLer
python3.14 -m venv .venv
.venv/bin/pip install -r requirements.lock
.venv/bin/pip install -e . --no-deps

Copy the example configuration:

mkdir -p ~/.config/swler
cp config.example.toml ~/.config/swler/config.toml

Find the IC-7300 audio source:

pactl list sources short

Put its name in audio_source inside ~/.config/swler/config.toml.

To verify the web install before setting up services:

.venv/bin/swler

Open http://127.0.0.1:8073/ on the host. From another device, replace 127.0.0.1 with the host's LAN or Tailscale address. Radio control remains disconnected until a separate rigctld is running; the service setup below handles that.

Run at boot

Included IC-7300 service

Find the radio's stable serial path:

ls -l /dev/serial/by-id/

Then prepare the two user services with that exact path:

radio_device="$(find /dev/serial/by-id -maxdepth 1 -type l -name '*IC-7300*' -print -quit)"
scripts/install.sh --device "$radio_device"

If radio_device is empty, the radio is off, disconnected, or uses a different device name. Power it on and inspect the ls output before continuing.

The installer does not run sudo, install packages, enable services, enable lingering, overwrite an existing config, or touch the database. It prints the remaining commands and expected results. In the usual setup they are:

systemctl --user enable --now swler-rigctld.service swler.service
loginctl enable-linger "$USER"

If your account cannot open the serial device, add it to dialout, then log out and back in:

sudo usermod -a -G dialout "$USER"

Run the read-only installation check whenever something seems off:

scripts/check.sh

scripts/uninstall.sh removes only SWLer-owned service files. It keeps your configuration, station database, and any independently managed rigctld unit.

Use an existing rigctld

If your radio already works through Hamlib, keep that daemon listening on 127.0.0.1:4532 in its normal protocol mode (not --vfo). In ~/.config/swler/config.toml, select the conservative profile:

rigctld_host = "127.0.0.1"
rigctld_port = 4532
radio_profile = "generic"

Prepare only the SWLer service:

scripts/install.sh --external-rigctld
systemctl --user enable --now swler.service

This mode never installs, starts, stops, or overwrites a rigctld service. Audio is configured separately with audio_source; working radio control does not imply that SWLer can guess the correct receive-audio source.

Using SWLer

Tap Listen once to attach browser audio. The pinned player says Loading stream…, Listening, or Buffering… so the short startup delay does not look like a hang. Tuning briefly shows Tuning… while the radio's read-back is verified; audio stays connected.

The Listen view is split into:

  • On air now — active UTC schedules
  • Up next — the next occurrence within seven days
  • Watch frequencies — unscheduled targets such as pirate activity and uncertain numbers-station frequencies

Quick Scan auditions the current on-air results, with optional Watch frequencies. It steps through catalog entries rather than sweeping a band. Choose a 15, 30, 45, or 60 second dwell; pause on something interesting, step back or forward, and resume when ready. Category scan picks one or more station categories instead — tap Pirates, Numbers, International, or a region such as Asia or Europe, and the queue is built from whatever those stations offer right now. Watch frequencies are included by default there, so unscheduled pirate watches are scannable out of the box. Save as preset keeps a category combination, dwell, and loop under a name; saved presets appear as one-tap tiles under the Scan bar, and a recipe preset re-resolves against the live schedule every time it starts, so it never goes stale. Manage sets builds named, server-persistent queues from exact station channels and also edits preset recipes.

The Stations tab manages custom records and source-backed entries. Custom stations can be deleted; source-backed stations are hidden instead so a later refresh does not resurrect them. User notes and tags survive catalog refreshes.

The seeded catalog is broad on purpose, but it is still a listening guide—not a promise that a transmitter is active or receivable from your location.

The Settings tab reports the selected radio profile, discovered modes, and a compatibility level:

  • Verified — the IC-7300 profile and its known control mappings
  • Compatible — generic tuning plus one or more discovered receive features
  • Tune only — frequency/mode control, with optional controls hidden
  • Incompatible — usually rigctld VFO mode or no shared SWLer mode

Use Copy compatibility report when reporting how another radio behaves.

Backup

The default database is ~/.local/share/swler/swler.db:

sqlite3 ~/.local/share/swler/swler.db ".backup '$HOME/swler-backup.db'"
cp ~/.config/swler/config.toml "$HOME/swler-config-backup.toml"

For restore, upgrades, API details, database rules, service internals, and the receive-command allowlist, see the technical reference.

Troubleshooting

Start with:

scripts/check.sh
journalctl --user -u swler.service
journalctl --user -u swler-rigctld.service

Common limitations:

  • An unplugged radio makes rigctld retry every 10 seconds. That is expected.
  • Generic support means Hamlib frequency/mode tuning first. Backend-specific filter, preamp, attenuator, and overflow meanings are intentionally not guessed.
  • SWLer and another rigctld client can both change one shared receiver; the latest command wins. Avoid simultaneous automation in two applications.
  • The EiBi refresh uses plain HTTP because the source host's HTTPS certificate is not usable. Refresh is manual and failures do not modify the catalog.
  • The S-meter is an approximate Hamlib conversion, not calibrated test gear.
  • Scan dwell is 15–60 seconds plus a 1.5-second post-tune settling interval.
  • Active scans do not survive an application restart; saved Scan Sets do.

Development

.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
.venv/bin/ruff check .
.venv/bin/mypy src

Read CONTRIBUTING.md before opening a pull request. The technical reference explains the code, and the implementation plan preserves the design history.

License and data sources

SWLer code and original assets are GPL-3.0-only. EiBi, Priyom, and HF Underground material has separate attribution and terms in THIRD_PARTY_NOTICES.md.

About

Receive-only shortwave listening web app for the Icom IC-7300

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages