The repository is available on GitHub.

The available documentation is:

  • Everything on this website, built from the /docs folder on the repository.

  • Rustdoc documentation, generated from docstrings, built using cargo doc --document-private-items --open

  • Also there are a lot of comments on the code because I tend to forget how it works quite fast.

Code style

  • We use rustfmt, run with cargo fmt.

  • Should follow the Style guidelines but 80 characters as line width.

  • Docstrings: Try to document everything, follow RFC-1574 without using links or examples.

  • Order of use in code (generally also alphabetically):

      pub mod ...;
      mod ...;
      pub use std::...;
      pub use thirdparty::...;
      pub use crate::...;
      use std::...;
      use thirdparty::...;
      use crate::...;


I’m using Jekyll, the website is built automatically by GitHub from the /docs folder. These are the steps to build the website locally:

sudo apt-get install ruby-dev
gem install bundler jekyll
cd docs
jekyll build --baseurl "$(pwd)/_site/"


  • I’m using a modification of Horizons-Jekyll-Theme.

  • Favicons generated using RealFaviconGenerator

  • Apparently, the theme used font-awesome to provide icons, I got rid of that.

  • Changed font to Open Sans and now I’m loading from default.html instead of style.css because it’s faster.

  • To set the sizes of youtube videos I use this.

Things to do

  • Bugs:

    • Decoded image preview is not removed when setting resample mode

    • Image preview is bugged when resizing

  • Important:

    • Look for defaults for yaw and scales?. See if yaw problems are caused by az_ref?. Ask someone.

    • Allow different timezones per filename.

    • The program eats RAM when opening bad custom TLE files.

    • More information link not working on Windows.

    • Add latitude longitude grid.

  • Someday:

    • Option to select a pre set path to save images (and notify DG4EK)

    • Implement histogram equalization on floats, before converting pixel values to integers.

    • Show user position on map. Add support for gpsd. Maybe using gpsd_proto.

    • Draw image over mercator (or at least equirectangular) projection.

    • Make seconds spinner add a minute when wrapping.

    • Check things that can panic/can fail:

      • Integer substraction.

      • Slicing/indexing.

      • Functions that can panic.

      • Something else?.

      • Make sure that Rate cant overflow when resampling against strange sample rates.

    • The error system is a mess. I’d like to make it consistent. Functions should add context to errors using for example map_err()?.

    • Use new Rust async syntax where needed?.

    • Show telemetry bands on GUI.

    • Log everything to a file, especially for Windows since it doesn’t have a console to see output.

    • Investigate about despeckle.

    • Make OSX binaries, I don’t have a Mac. I should cross-compile or get a virtual machine to work?.

    • Check OSX build dependencies, now on GNU/Linux we need libssl-dev.

    • Compile as a library and create an Android client

    • Improve syncing performance. Make it faster and more resilent to noise, maybe working with the mean and variance?. Especially for Raspberry Pi.

    • Live decoding, from a TCP stream or using librtlsdr or from audio.

    • Add man page.

    • Show panics from the decoding thread on GUI. Looks like I have to wait until rust creates a simple way, the current alternatives are:

      • std::thread::JoinHandle::join() returns Err() on a panic, but blocks the GUI thread.

      • std::panic::catch_unwind works “only” for unwinding panics, maybe it’s enough?

      • #[panic_handler] looks useful for no_std applications.



  • Install rustup

  • sudo apt install libgtk-3-dev libssl-dev.

If building with GUI:

  • sudo apt install libgtk-3-dev

  • cargo build --release.

If building without GUI:

  • cargo build --release --no-default-features.

To run the program:


If you are moving the executable somewhere, it is important to move along the res/ folder, because it is needed in the working directory during runtime. For example:

mkdir ~/Desktop/noaa-apt/
cp ./target/release/noaa-apt ~/Desktop/noaa-apt/
cp -r ./res ~/Desktop/noaa-apt/
cp ./build/ ~/Desktop/noaa-apt/

GNU/Linux portable, or cross-compilation

The binaries uploaded in GitHub are built inside a docker container, in a way that produces a “portable” program that can be run on most machines. This means that most libraries are statically compiled.

I can’t make gtk-rs to work with the x86_64-unknown-linux-musl target, so I’m building with the default x86_64-unknown-linux-gnu on the oldest possible Debian image. I think that this way, the binary works on any linux with GLIBC newer than the one used when building.

In the end, I build all the GNU/Linux releases with a Docker image.

  • Install Docker.

  • Move to root folder on this repository.

  • docker build ./build/linux-gnu-docker/ -t noaa-apt-linux-build-image

  • docker run -v $(pwd):/home/rustacean/src -it noaa-apt-linux-build-image ALL

In this case, the build was done for ALL targets. You can replace ALL for one of the following: X86_64_GUI, X86_64_GUI_DEB, X86_64_NOGUI, ARMV7_GUI, ARMV7_NOGUI, AARCH64_GUI, AARCH64_NOGUI.

The resuting binaries/packages will be found at ./target/docker_builds.

Mac / OSX

One option is to use the install script like the following:

  • Download the source code zip file and extract it somewhere.

  • Move to the downloaded folder

    cd Downloads/noaa-apt-1.4.1/
  • Run the installer

  • Then run the program


Another option is to do all the steps manually (This is a summary of this extensive installation guide):

  • Install rustup:

    curl --proto '=https' --tlsv1.2 -sSf | sh
    source $HOME/.cargo/env
  • Install dependencies via Homebrew.

    /bin/bash -c "$(curl -fsSL"
    brew install gtk+3 adwaita-icon-theme openssl
  • Download the source code zip file and extract it somewhere.

  • Move to the downloaded folder

    cd Downloads/noaa-apt-1.4.1/
  • Compile

    export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/
    cargo build --release
  • Then run the program


There has been also a succesful installation by installing first in OSX Catalina and then copying the folder to OSX Sierra. Apparently it is necessary to have Homebrew and have the packages updated, including gtk+3, adwait-icon-theme, openssl and harfbuzz.

Android with Termux

You will need a good device and quite a lot of patience. The instructions to compile are the same as in GNU/Linux. It may be necesary to set the OPENSSL_DIR variable to point to the correct path. If someone knows please write a guide.

Windows portable

I never tried to compile from Windows, I cross-compile from GNU/Linux to Windows. I tried to get a mingw64-gtk environment to work on Debian without success. So I use a modification of a Docker image I found here.

  • Install Docker.

  • Move to root folder on this repository.

  • docker build ./build/windows-gnu-docker/ -t noaa-apt-windows-build-image

  • docker run -v $(pwd):/home/rustacean/src -it noaa-apt-windows-build-image

The binaries/packages are on ./target/docker_builds

Raspberry Pi

I’m building it from my x86_64 computer using the same docker container I use for GNU/Linux portables. If you want to build it from your Raspberry Pi, you have to follow the normal steps for GNU/Linux.


Unit tests are located on the bottom of every module.

cargo test

There is an additional test that needs a API key.

N2YO_KEY=ASJKDH... cargo test -- --ignored

Also, for GNU/Linux I have a bash script that runs the program on WAV files located on /test/. Results are on /test/results/, check with Audacity.


I use Clippy too:

  • cargo clippy -- -A clippy::ptr_arg -A clippy::match_bool -A clippy::manual_range_contains -A clippy::module_inception: Should have no warnings.

  • cargo clippy -- -A clippy::ptr_arg -W clippy::pedantic: Check once in a while but ignore most of the lints

Release checklist

  • Update dependency version constraints on Cargo.toml: cargo install cargo-edit; cargo upgrade.

  • Update dependencies (on Cargo.lock): cargo update.

  • Unit tests: cargo test.

  • Get previous tags from remote and check latest version, just in case:

      git fetch --tag
      git tag -l
  • Increment version number on /Cargo.toml.

  • Increment version number on /docs/version_check.

  • Increment version number on /src/program.rc.

  • Increment version number of /src/default_settings.toml if necessary.

  • Increment version number of settings file in /src/ if necessary.

  • Copy /src/default_settings.toml to /docs/default_settings.toml if necessary.

  • Write changelog on /debian/changelog.

  • Edit the Downloads page on the website, point to the new packages that are going to be uploaded. Also change the version in the install command.

  • Build using Docker for:

    • GNU/Linux.

    • GNU/Linux without GUI.

    • Windows.

  • Check required glibc version, should be less than the version shown on the Download page. Use /build/, e.g.: ./build/ ./target/docker_builds/noaa-apt-?.?.?-x86_64-linux-gnu/noaa-apt

  • Update downloads page with dependencies from /debian/noaa-apt/DEBIAN/control

  • Check archives, names should be:

    • noaa-apt-?.?.?

    • noaa-apt-?.?.?

    • noaa-apt-?.?.?

    • noaa-apt-?.?.?

    • noaa-apt-?.?.?

    • noaa-apt-?.?.?

    • noaa-apt_?.?.?-1_amd64.deb

    • noaa-apt-?.?.?

  • Test both GNU/Linux builds using /test/

  • Test Windows version.

  • Test Raspberry Pi version.

  • Optionally test .deb on Ubuntu VM.

  • Create tag on git, e.g.: git tag v0.9.2.

  • Push tag, e.g.: git push origin v0.9.2.

  • Edit release on GitHub. Leave “Release title” empty, leave changelog as description. Upload files.

  • Ask Sylogista to update the AUR package.

  • Ask Tom Repetti to update the NixOS Package.

Check for updates

The program sends a HTTP GET request and receives the latest version available, the URL is{current version}.

The currently installed version is sent just in case I want to track which versions are being used by people. Anyways, for now I delegated the noaa-apt to Github and version_check is just a static file being served using Github pages, so currently I’m not logging any information. In the future I won’t log anything other than the currently installed version.

If you want to disable this you can do it from the configuration file.


  • When I tried to UDP stream from GQRX to localhost it didn’t work, I had to change the address to

  • Sizes for Windows icons: 16x16, 32x32, 48x48, and 256x256. Icons generated using the script /build/

  • Decode of argentina.wav on Raspberry Pi took approx 36s with WXtoImg (pristine, no map, no despeckle) and 46s with noaa-apt using the fast profile.

Thank you to

  • For writing a blog post.

  • Arcadie Z.: Histogram equalization, image rotation, false color, fixes and more.

  • pietern: I took the AM demodulator from his apt137 decoder.

  • Ossi Herrala: Did some fixes and updated dependencies.

  • Nodraak: Added tips when saving files.

  • Dirk Lison: Testing and filename guessing for WXtoIMG.

  • Grant T. Olson: Early OSX build instructions

  • Sasha Engelmann and Bill Liles: Further OSX build instructions.

  • FMighty: Helped with cross compilation to Raspberry Pi.

  • Sylogista: Maintains an AUR package.

  • Tom Repetti: Packaged program for NixOS.

  • ButchOfBurdock: Instructions for compilation in Android + Termux.

  • Peter Vogel: For writing about noaa-apt on the web.

  • wren84 and Florentin314: Reported problems with decoded images.

  • Gagootron, xxretartistxx and unknownantipatriot: Provided example images of missing samples.

  • BGNLouie, nosduh2, samarrangepas, KiwiEntropy, budude2, K2SDR, K6KZO, TheLAX18: Provided recordings to test map overlays.

  • JKamue, Kind-Shame: Provided example images for website.

  • To everyone who reported issues or sent me emails showing their images!