substation 0.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- substation-0.5.1/.github/workflows/publish.yml +48 -0
- substation-0.5.1/.gitignore +13 -0
- substation-0.5.1/INSTALL.md +269 -0
- substation-0.5.1/LICENSE +661 -0
- substation-0.5.1/PKG-INFO +913 -0
- substation-0.5.1/README.md +881 -0
- substation-0.5.1/examples/scan_demo.py +107 -0
- substation-0.5.1/examples/scan_osc.py +101 -0
- substation-0.5.1/pyproject.toml +133 -0
- substation-0.5.1/setup.cfg +4 -0
- substation-0.5.1/substation/__init__.py +46 -0
- substation-0.5.1/substation/__main__.py +15 -0
- substation-0.5.1/substation/antenna.py +371 -0
- substation-0.5.1/substation/cli.py +408 -0
- substation-0.5.1/substation/config.py +913 -0
- substation-0.5.1/substation/config.yaml.default +635 -0
- substation-0.5.1/substation/constants.py +225 -0
- substation-0.5.1/substation/devices/__init__.py +113 -0
- substation-0.5.1/substation/devices/base.py +168 -0
- substation-0.5.1/substation/devices/file.py +272 -0
- substation-0.5.1/substation/devices/hackrf.py +374 -0
- substation-0.5.1/substation/devices/rtlsdr.py +167 -0
- substation-0.5.1/substation/devices/soapysdr.py +758 -0
- substation-0.5.1/substation/dsp/__init__.py +3 -0
- substation-0.5.1/substation/dsp/demodulation.py +853 -0
- substation-0.5.1/substation/dsp/filters.py +348 -0
- substation-0.5.1/substation/dsp/noise_reduction.py +485 -0
- substation-0.5.1/substation/osc_sender.py +220 -0
- substation-0.5.1/substation/recording.py +1011 -0
- substation-0.5.1/substation/scanner.py +2033 -0
- substation-0.5.1/substation.egg-info/PKG-INFO +913 -0
- substation-0.5.1/substation.egg-info/SOURCES.txt +55 -0
- substation-0.5.1/substation.egg-info/dependency_links.txt +1 -0
- substation-0.5.1/substation.egg-info/entry_points.txt +3 -0
- substation-0.5.1/substation.egg-info/requires.txt +17 -0
- substation-0.5.1/substation.egg-info/scm_file_list.json +51 -0
- substation-0.5.1/substation.egg-info/scm_version.json +8 -0
- substation-0.5.1/substation.egg-info/top_level.txt +1 -0
- substation-0.5.1/tests/__init__.py +0 -0
- substation-0.5.1/tests/conftest.py +71 -0
- substation-0.5.1/tests/iq_generators.py +67 -0
- substation-0.5.1/tests/test_antenna.py +127 -0
- substation-0.5.1/tests/test_cli.py +90 -0
- substation-0.5.1/tests/test_config.py +438 -0
- substation-0.5.1/tests/test_config_supervisor.py +28 -0
- substation-0.5.1/tests/test_constants.py +36 -0
- substation-0.5.1/tests/test_demodulation.py +819 -0
- substation-0.5.1/tests/test_devices.py +193 -0
- substation-0.5.1/tests/test_events.py +179 -0
- substation-0.5.1/tests/test_filters.py +215 -0
- substation-0.5.1/tests/test_noise_reduction.py +339 -0
- substation-0.5.1/tests/test_osc_sender.py +297 -0
- substation-0.5.1/tests/test_recording.py +507 -0
- substation-0.5.1/tests/test_scanner_channels.py +189 -0
- substation-0.5.1/tests/test_scanner_detection.py +371 -0
- substation-0.5.1/tests/test_scanner_transitions.py +131 -0
- substation-0.5.1/tests/test_soapysdr.py +449 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Publishes a release whenever a version tag is pushed. Versioning is driven by
|
|
4
|
+
# git tags via setuptools-scm, so `git tag v0.6.0 && git push --tags` is the
|
|
5
|
+
# whole release flow. Uses PyPI Trusted Publishing (OIDC) — no API token is
|
|
6
|
+
# stored. The build runs in isolation and only needs the build backend
|
|
7
|
+
# (setuptools + setuptools-scm), so it never installs the RTL-SDR / HackRF /
|
|
8
|
+
# SoapySDR runtime dependencies. Action versions matter: older majors run on a
|
|
9
|
+
# retired Node runtime and GitHub fails the job (same pattern as Subsequence).
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags:
|
|
14
|
+
- "v*"
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
name: Build distributions
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v7
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0 # full history + tags so setuptools-scm can derive the version
|
|
24
|
+
- uses: actions/setup-python@v6
|
|
25
|
+
with:
|
|
26
|
+
python-version: "3.12"
|
|
27
|
+
- name: Build sdist and wheel
|
|
28
|
+
run: pipx run build
|
|
29
|
+
- name: Check metadata
|
|
30
|
+
run: pipx run twine check dist/*
|
|
31
|
+
- uses: actions/upload-artifact@v7
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
|
|
36
|
+
publish:
|
|
37
|
+
name: Publish to PyPI
|
|
38
|
+
needs: build
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
environment: pypi
|
|
41
|
+
permissions:
|
|
42
|
+
id-token: write # required for Trusted Publishing
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/download-artifact@v8
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Substation Installation Guide
|
|
2
|
+
|
|
3
|
+
Platform-specific setup for SDR drivers, system dependencies, and the Python environment. See [README.md](README.md) for usage, configuration, and features.
|
|
4
|
+
|
|
5
|
+
Tested on:
|
|
6
|
+
- Debian 12 / Ubuntu 24.04 / Raspberry Pi OS (Bookworm)
|
|
7
|
+
- Fedora 43 Server (x86_64)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. RTL-SDR Blog V4 Driver
|
|
12
|
+
|
|
13
|
+
The RTL-SDR Blog V4 requires the rtlsdrblog fork — the standard osmocom drivers are missing required symbols (e.g. `rtlsdr_set_dithering`).
|
|
14
|
+
|
|
15
|
+
### Debian / Ubuntu / Raspberry Pi OS
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Remove any existing RTL-SDR packages to avoid conflicts
|
|
19
|
+
sudo apt purge ^librtlsdr
|
|
20
|
+
sudo rm -rvf /usr/lib/librtlsdr* /usr/include/rtl-sdr* \
|
|
21
|
+
/usr/local/lib/librtlsdr* /usr/local/include/rtl-sdr* \
|
|
22
|
+
/usr/local/include/rtl_* /usr/local/bin/rtl_*
|
|
23
|
+
|
|
24
|
+
# Install build tools
|
|
25
|
+
sudo apt update
|
|
26
|
+
sudo apt install -y libusb-1.0-0-dev git cmake pkg-config build-essential
|
|
27
|
+
|
|
28
|
+
# Clone and build the RTL-SDR Blog fork
|
|
29
|
+
git clone https://github.com/rtlsdrblog/rtl-sdr-blog.git rtl-sdr
|
|
30
|
+
cd rtl-sdr
|
|
31
|
+
mkdir build && cd build
|
|
32
|
+
cmake ../ -DINSTALL_UDEV_RULES=ON
|
|
33
|
+
make
|
|
34
|
+
sudo make install
|
|
35
|
+
sudo cp ../rtl-sdr.rules /etc/udev/rules.d/
|
|
36
|
+
sudo ldconfig
|
|
37
|
+
|
|
38
|
+
# Blacklist the default DVB-T driver so it doesn't claim the SDR as a TV tuner
|
|
39
|
+
echo 'blacklist dvb_usb_rtl28xxu' | sudo tee --append /etc/modprobe.d/blacklist-dvb_usb_rtl28xxu.conf
|
|
40
|
+
|
|
41
|
+
cd ../..
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Fedora
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Remove any existing RTL-SDR packages
|
|
48
|
+
sudo dnf remove 'rtl-sdr*' 'librtlsdr*'
|
|
49
|
+
sudo rm -rvf /usr/lib/librtlsdr* /usr/lib64/librtlsdr* \
|
|
50
|
+
/usr/include/rtl-sdr* /usr/local/lib/librtlsdr* \
|
|
51
|
+
/usr/local/lib64/librtlsdr* /usr/local/include/rtl-sdr* \
|
|
52
|
+
/usr/local/include/rtl_* /usr/local/bin/rtl_*
|
|
53
|
+
|
|
54
|
+
# Install build tools
|
|
55
|
+
sudo dnf group install -y development-tools
|
|
56
|
+
sudo dnf install -y gcc gcc-c++ libusb1-devel git cmake pkgconf
|
|
57
|
+
|
|
58
|
+
# Clone and build the RTL-SDR Blog fork
|
|
59
|
+
git clone https://github.com/rtlsdrblog/rtl-sdr-blog.git rtl-sdr
|
|
60
|
+
cd rtl-sdr
|
|
61
|
+
mkdir build && cd build
|
|
62
|
+
cmake ../ -DINSTALL_UDEV_RULES=ON
|
|
63
|
+
make
|
|
64
|
+
sudo make install
|
|
65
|
+
sudo cp ../rtl-sdr.rules /etc/udev/rules.d/
|
|
66
|
+
sudo ldconfig
|
|
67
|
+
|
|
68
|
+
# Blacklist the default DVB-T driver
|
|
69
|
+
echo 'blacklist dvb_usb_rtl28xxu' | sudo tee --append /etc/modprobe.d/blacklist-dvb_usb_rtl28xxu.conf
|
|
70
|
+
|
|
71
|
+
cd ../..
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 2. System Optimisation (USB Buffering)
|
|
77
|
+
|
|
78
|
+
High sample rates (e.g. HackRF at 20 MHz) require more USB buffer memory than the kernel default.
|
|
79
|
+
|
|
80
|
+
### Debian / Ubuntu / Raspberry Pi OS
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Edit the kernel command line
|
|
84
|
+
sudo nano /boot/firmware/cmdline.txt
|
|
85
|
+
|
|
86
|
+
# Add the following to the end of the existing (single) line:
|
|
87
|
+
usbcore.usbfs_memory_mb=1000
|
|
88
|
+
|
|
89
|
+
# Reboot for the change to take effect
|
|
90
|
+
sudo reboot
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Fedora
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Add the kernel parameter via grubby (Fedora's preferred method)
|
|
97
|
+
sudo grubby --update-kernel=ALL --args="usbcore.usbfs_memory_mb=1000"
|
|
98
|
+
|
|
99
|
+
# Reboot for the change to take effect
|
|
100
|
+
sudo reboot
|
|
101
|
+
|
|
102
|
+
# After reboot, verify the parameter is active
|
|
103
|
+
cat /proc/cmdline | grep usbfs_memory_mb
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 3. OS Dependencies
|
|
109
|
+
|
|
110
|
+
### Debian / Ubuntu / Raspberry Pi OS
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Audio and maths libraries
|
|
114
|
+
sudo apt install -y libsndfile1 libsndfile1-dev python3-setuptools python3-dev
|
|
115
|
+
|
|
116
|
+
# HackRF drivers and utilities
|
|
117
|
+
sudo apt install -y libhackrf-dev hackrf
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Fedora
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Audio and maths libraries
|
|
124
|
+
sudo dnf install -y libsndfile libsndfile-devel python3-setuptools python3-devel
|
|
125
|
+
|
|
126
|
+
# HackRF drivers and utilities
|
|
127
|
+
sudo dnf install -y hackrf hackrf-devel
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 4. SoapySDR + AirSpy Support
|
|
133
|
+
|
|
134
|
+
Required only if using AirSpy R2, AirSpy HF+ Discovery, or other SoapySDR-compatible devices.
|
|
135
|
+
|
|
136
|
+
### Debian / Ubuntu / Raspberry Pi OS
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Install SoapySDR core and Python bindings
|
|
140
|
+
sudo apt install -y soapysdr-tools python3-soapysdr
|
|
141
|
+
|
|
142
|
+
# Install device-specific SoapySDR modules (install only what you need)
|
|
143
|
+
sudo apt install -y soapysdr-module-airspy # AirSpy R2
|
|
144
|
+
sudo apt install -y soapysdr-module-airspyhf # AirSpy HF+ Discovery
|
|
145
|
+
|
|
146
|
+
# If soapysdr-module-airspyhf is not available in your distro's repos
|
|
147
|
+
# (e.g., Raspberry Pi OS), build from source instead:
|
|
148
|
+
sudo apt install -y libairspyhf-dev libsoapysdr-dev cmake
|
|
149
|
+
git clone https://github.com/pothosware/SoapyAirspyHF.git
|
|
150
|
+
cd SoapyAirspyHF
|
|
151
|
+
mkdir build && cd build
|
|
152
|
+
cmake ..
|
|
153
|
+
make
|
|
154
|
+
sudo make install
|
|
155
|
+
cd ../..
|
|
156
|
+
|
|
157
|
+
# Verify SoapySDR can see connected devices
|
|
158
|
+
SoapySDRUtil --find
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Fedora
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Install SoapySDR core and Python bindings
|
|
165
|
+
sudo dnf install -y SoapySDR SoapySDR-devel python3-SoapySDR
|
|
166
|
+
|
|
167
|
+
# Install device modules from the Fedora repos
|
|
168
|
+
sudo dnf install -y soapy-rtlsdr # RTL-SDR via SoapySDR
|
|
169
|
+
sudo dnf install -y soapy-airspyhf # AirSpy HF+ Discovery
|
|
170
|
+
|
|
171
|
+
# AirSpy R2 module is not in the Fedora repos — build from source:
|
|
172
|
+
sudo dnf install -y airspyone_host-devel SoapySDR-devel cmake
|
|
173
|
+
git clone https://github.com/pothosware/SoapyAirspy.git
|
|
174
|
+
cd SoapyAirspy
|
|
175
|
+
mkdir build && cd build
|
|
176
|
+
cmake ..
|
|
177
|
+
make
|
|
178
|
+
sudo make install
|
|
179
|
+
cd ../..
|
|
180
|
+
|
|
181
|
+
# Verify SoapySDR can see connected devices
|
|
182
|
+
SoapySDRUtil --find
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 5. Python Environment
|
|
188
|
+
|
|
189
|
+
The same for all platforms.
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# If using SoapySDR devices (AirSpy, etc.), the venv MUST inherit system
|
|
193
|
+
# packages so it can access the system-installed python3-soapysdr bindings:
|
|
194
|
+
python3 -m venv --system-site-packages venv
|
|
195
|
+
|
|
196
|
+
# If you already have an existing venv, enable system packages on it:
|
|
197
|
+
# sed -i 's/include-system-site-packages = false/include-system-site-packages = true/' /path/to/venv/pyvenv.cfg
|
|
198
|
+
|
|
199
|
+
# If only using RTL-SDR or HackRF (no SoapySDR), a standard venv is fine:
|
|
200
|
+
# python3 -m venv venv
|
|
201
|
+
|
|
202
|
+
source venv/bin/activate
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Then install substation. Most users want one of the first two:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# From PyPI (stable release)
|
|
209
|
+
pip install substation
|
|
210
|
+
|
|
211
|
+
# From GitHub (latest, no release needed)
|
|
212
|
+
pip install git+https://github.com/simonholliday/substation.git
|
|
213
|
+
|
|
214
|
+
# From a local clone, editable — for development
|
|
215
|
+
pip install -e .
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The default configuration ships inside the package, so no clone is needed. After installing, create an editable starter config in your working directory:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
substation --init # writes ./config.yaml (the fully-commented defaults)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Optional extras
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# OSC event forwarding (for MIDI sequencer, sampler, etc.)
|
|
228
|
+
pip install "substation[osc]"
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Supervisor dashboard** (real-time WebSocket state broadcast) is a separate package installed from GitHub — it is *not* a PyPI extra, because PyPI does not permit direct-URL dependencies:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
pip install git+https://github.com/simonholliday/supervisor.git
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
While the supervisor repository is private, this install uses SSH (`git+ssh://git@github.com/...`) and requires a GitHub SSH key on the machine — see [GitHub's SSH setup guide](https://docs.github.com/en/authentication/connecting-to-github-with-ssh). The scanner runs normally with the dashboard disabled if the package isn't present.
|
|
238
|
+
|
|
239
|
+
After installing supervisor, enable the dashboard in `config.yaml`:
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
supervisor:
|
|
243
|
+
enabled: true
|
|
244
|
+
port: 9004 # default
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The scanner logs `Supervisor dashboard server started on ws://0.0.0.0:9004` when it starts. If the extra is not installed, a warning is logged and the scan proceeds without the dashboard.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 6. Verification
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# List available bands from the default configuration
|
|
255
|
+
substation --list-bands
|
|
256
|
+
|
|
257
|
+
# Or using the Python module directly
|
|
258
|
+
python3 -m substation --list-bands
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Platform-Specific Notes
|
|
264
|
+
|
|
265
|
+
### Fedora
|
|
266
|
+
|
|
267
|
+
- **SELinux**: Fedora enables SELinux in enforcing mode by default. If USB devices aren't accessible even after udev rules are in place, check for denials with `sudo ausearch -m avc -ts recent`. Typically the udev rules are sufficient.
|
|
268
|
+
- **Firewalld**: If using OSC event forwarding or other network features, you may need to open ports: `sudo firewall-cmd --add-port=9000/udp --permanent && sudo firewall-cmd --reload`.
|
|
269
|
+
- **lib vs lib64**: Fedora uses `/usr/lib64` for 64-bit libraries. The `ldconfig` step after building RTL-SDR should handle this, but if you get "library not found" errors, check that `/usr/local/lib64` is listed in `/etc/ld.so.conf.d/` and re-run `sudo ldconfig`.
|