Thanks for helping make the project useful on real radios, not only on ideal mock data. This project is receive-only, but RF and Wi-Fi metadata are still sensitive. Keep contributions reproducible, conservative in their claims and safe for contributors who do not own the same hardware.
Start with Architecture and Platforms and hardware.
python -m venv .venv
# Windows PowerShell: .\.venv\Scripts\Activate.ps1
# POSIX shells: source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
python -m pytest tests -q
python -m ruff check pluto_wifi_surveyor tests examples gnuradio
python -m compileall pluto_wifi_surveyorAdd hardware only when working with a real Pluto:
python -m pip install -e '.[hardware,dev]'Run the GUI without hardware before changing device code:
python -m pluto_wifi_surveyor --mock --mock-scenario dual-band
python -m pluto_wifi_surveyor --mock --mock-scenario dual-plutoReplay tests should use a small capture directory written through
save_iq_capture; do not commit third-party RF recordings or captures that
contain identifiers without explicit permission.
- Keep UI work in
gui/; widgets must not open devices or perform I/O. - Keep scanner backends in
scanner/; they returnCaptureResultand do not own analysis or Tk state. - Keep measurement math in
analysis/. Aggregation must be duration/sample weighted and average power in linear units, not dB. - Keep network identity in
wifi/. Never create an SSID/BSSID record from spectrum energy alone. - Preserve the one-Pluto-owner rule. The integrated decoder uses captured IQ; an external GNU Radio decoder needs another radio rather than a shared URI.
- Treat session JSON, replay capture metadata and UDP formats as public compatibility contracts. Version or document incompatible changes.
Every functional change needs focused tests in tests/, plus regression
coverage for its public behaviour. Prefer deterministic mock, synthetic IQ
or replay inputs over hardware-only tests.
Useful groups include:
test_power.py,test_occupancy.py,test_measure.py: RF math;test_aggregation.py,test_panorama.py,test_spectrum.py: weighting, continuity and display-model calculations;test_ofdm_beacon_decoder.py,test_management_parser.py,test_udp_receiver.py: decoder and frame handling;test_engine.py,test_integration.py,test_mock_backend.py: lifecycle and scanner behaviour;test_gui_smoke.py: Tk integration (may skip without a display);test_session_export.py,test_replay.py,test_csv_export.py: file compatibility.
Before opening a pull request, run the commands in Development setup. If a GUI test skips because the runner has no display, say so; do not claim it passed. If hardware validation was performed, include the device model, firmware, URI transport, OS, sample rate, gain, selected band and whether the Pluto uses extended tuning.
Keep a pull request narrow and explain:
- The user-visible problem and expected behaviour.
- The evidence model: whether the change affects RF activity, decoded network identity, or both.
- Any RF assumptions, calibration limits or compatibility impact.
- Tests run and their result.
- Hardware validation, if any, without publishing private BSSIDs, SSIDs, locations, capture files or credentials.
Use conventional, readable commits where practical. Do not combine large formatting rewrites with a behavioural change. Maintainers may request a replay fixture, a mock scenario or an update to documentation whenever a UI claim, protocol contract or user workflow changes.
- Update the version in
pyproject.tomland release notes/changelog if one is introduced. - Run the full test, Ruff and compile commands above from a clean checkout.
- Smoke-test mock mode on at least one supported desktop platform.
- Validate installation from the built wheel in a fresh virtual environment.
- If changing file or network contracts, test loading an old session/replay fixture and update schema/protocol documentation.
- Review dependency changes, licenses and security advisories.
- Confirm no private capture, credentials, device URI, access token or local configuration was included in the release artifacts.