Thursday, February 20, 2020

HF APRS with JS8Call

How to configure JS8Call to report your location into the APRS network

JS8Call is a derivative of the WSJT-X application, based on the robustness of FT8 it's primarily for keyboard-to-keyboard message passing. See the JS8Call homepage and JS8Call site.

JS8Call activity (last 15 mins) - pskreporter.

Among some of its features is the ability to report your position into the APRS network via other stations running JS8Call:
  1. Find your 10 character grid square, K7FRY has a great tool Find QTH or map square built in Google maps that lets you find your location, click on the map and it displays your 10 character grid square.
  2. In JS8Call, File > Settings > General, enter the grid square in the My Maidenhead Grid Locator box.
  3. In JS8Call, File > Settings > Save messages > add a new message: @APRSIS GRID <MYGRID12> and OK to save. Note: JS8Call will replace "<MYGRID12>" with the value from My Maidenhead Grid Locator set in step 2 when the saved message is selected and sent next. The number sets the number of grid square characters to send, 4 being the minimum. Higher the number higher the accuracy of the location reported.
  4. In the main JS8Call window right click in the Message(s) or outgoing message box > Saved Messages > select your saved @APRSIS message to send it.
When I selected the saved message to send, my location appeared on with-in about a minute:

(Click for larger/clearer image)
KL3NO was my previous callsign

Here I am, shows it came from JS8, was on 30m band, and a SNR of -12dB. It was received by one of WB6CXC's dedicated gateway receivers.

During 2020 which was still fairly low in the solar cycle 40m was the most reliable at any time, even during the daytime where the range is limited due to D-layer absorption.

In 2024 where we're coming into a solar maximum 20m is the better band during the day time, and even into the evening and night. 40m would still be a better choice at night when the daytime D-layer absorption is no longer present.

This project was recently posted on Hackaday, the comments have interesting and useful info related to APRS.

Taking it Mobile

The VHF APRS coverage is usually very good in many places, but also non-existent in more remote and sparsely populated areas. An alternative is to use HF radio and JS8Call to send position reports.

This was work in progress in 2020 then the project got shelved. The original setup used a Raspberry Pi running Buster Desktop. I resurrected the project again in Feb 2024, this time around I'm using a Dell Latitude 7490 laptop (with a car charger) running Debian 12 (Bookworm) with MATE desktop.

Taking it mobile to draw lines on a map ( is fairly easy as the software to do this exists, it's just a matter of plugging the pieces together, and configuring the options.

Using JS8Call for this has a number good points:
  • The software to do this already exists.
  • JS8 is FT8 re-worked for chat and message handling, it retains the weak signal and decoder performance of FT8, including FEC (forward error correction) and robustness against noise, QRM, and ionospheric effects.
  • It takes two frames to transmit the position report, 30 seconds on normal mode (50 Hz).
  • Anyone running JS8Call is a monitor for the @APRSIS messages, so we have plenty of stations who can receive and pass the position report into the APRS network for us.
  • All we have to do is configure the transmitting end.

JS8CallUtilities_V2 is used to read the GPS data, which then sends the @APRSIS GRID message to JS8Call to transmit. Both can be configured to do this on start up (set and forget).

The only custom part I had to do was write a shell script to handle power disruptions to the rig (vehicle starts) which will cause a rig control error. The script monitors for rig control errors, closes down and then restarts the applications when the rig USB port is detected (rig has power again).

Below there are both bash shell (Linux) and PowerShell (Windows) versions of the script needed to handle power disruptions to the radio.

My mobile IC-7100 and Hamstick antenna install / setup info here.


Debian 12 (Bookworm), on a Dell Latitude 7490.

This is what I chose to use / had available.

Text install, SSH server, MATE desktop. I tried XFCE first, but its power management caused problems with digi apps functioning when the screen saver ran / screen was blanked.

Specific to the Dell Latitude 7490, the Intel 915 graphics causes the system to lockup during boot or after starting the GUI (related to power management - Intel Graphics - ArchWiki):
  • Grub boot menu > e > append i915.enable_dc=0 to the end of the linux /boot/vmlinuz line. 
  • After system boots up, edit /etc/default/grub, append i915.enable_dc=0 to the end of  GRUB_CMDLINE_LINUX_DEFAULT= line.
  • Run update-grub

IP Addresses: ip -c a

Groups, add our selves to dialout (needed for USB/serial port access), and sudo:
  • su -
  • Enter root password
  • usermod -aG dialout,sudo <user name>
  • logout ; logout

Update vi to vim, I'm old fashioned and like vi/vim editor: sudo apt-get install vim

VNC, for remote console session access (I find it useful during setup/testing etc):
  • sudo apt-get install tigervnc-scraping-server tigervncpasswd
  • vncpasswd
  • x0vncserver -display :0 -localhost no
  • Note: The console session needs to be logged in first.
  • Connect VNC client (port 5900), note the connection is not secured or encrypted. If thats a problem, either start x0vncserver with -localhost yes option and tunnel the port over SSH or figure out TLS etc.
  • killall x0vncserver (quit the vnc server).
  • Having the VNC server start / allow access to the console session with-out having to log it in first would be nice.
    • Systemd unit for x0vncserver (TigerVNC Wiki), the script works when manually run, but the systemd unit fails to start it.
    • Changed PARAMS="-display :0 -localhost no" and copied .vnc/passwd from my home dir to /root/.vnc/passwd 
    • Out of everything I have searched for and tried, this gets the closest, but requires to be manually run from an SSH session after a reboot or logout from the desktop.
    • At least there is now the ability to logout of the desktop or reboot, run via SSH to restart the vnc server, and regain access to the desktop with out physically logging in the console session.

Edit MATE Menus

The digi mode apps get added to different Applications menu groups.

System (menu) > Preferences > Look and Feel > Main Menu

If not present install Mozo menu editor

sudo apt-get install mozo

This is the end of Debian 12 specific configuration, below ~ should ~ work on any Debian based system (Linux Mint, Raspberry Pi OS, Ubuntu etc).



GlobalSat BU-353-S4 USB GPS Receiver is what I got/have/used.

To get this GPS working:
Plug the GPS in
    sudo dmesg

    Note the /dev/ttyUSBx device name the GPS was mounted with.
      ls -l /dev/serial/by-id/

      Note the name of the link pointing to the /dev/ttyUSBx device name.
      sudo apt-get install gpsd gpsd-clients
      Edit /etc/default/gpsd to match

      GPSD_OPTIONS="-n -G -b"

      DEVICES matches the GPS serial link name, one line.

      USBAUTO="false" disables hot plugging. If enabled (true) gpsd will attempt to get GPS data from any serial device that is connected and prevents other applications from accessing the port, including the radio USB port!

      Restart the GPSD service:
      1. sudo systemctl restart gpsd
      2. gpsmon
        Had a GPS fix, Ctrl C to quit.

        Enable the service to start at boot:
        • sudo systemctl enable gpsd

        An alternative to using the symlink as above is to use udev rules, shows how to set these up. 

        Sync Time via GPS 

        I got the details from here:
        1. Install Chrony: sudo apt-get install chrony
        2. Edit /etc/chrony/chrony.conf add this to end of file (one line): refclock SHM 0 offset 0.5 delay 0.2 refid NMEA
        3. Restart Chrony:
          1. sudo systemctl restart chrony
        4. Check Chrony's sources: chronyc sources -v
        5. Or to have it update every second in a terminal window: watch -n 1 chronyc sources

        The offset is specific to the GPS, in my case using 0.5 put it off by about 200ms compared to NTP servers, Chrony marked source state as 'maybe be in error', but would switch to using it ok with no internet connection.

        See Millisecond accurate Chrony... for a dive into tuning the config with the GPS.

        To figure out the offset for my specific GPS:
        • I commented out the pool address.
        • Temporally added three of the nearest NIST time servers.
        • Enabled logging.
        • Set makestep to 0.1 3 (helps quickly change time if its off more than 100ms on startup).
        • Set the GPS offset to 0.000 noselect.
        • Restarted Chrony, let it run for an hour (longer gets a better average).
        Followed the steps to get the data into Excel and averaged the time offset column. The figure I got was 3.05E-01 or 305ms

        I changed the Chrony conf back to using the pool address, commented out the NIST servers, updated the GPS refclock line and remove noselect, only changes to the file in the end are:

        makestep 0.1 3
        refclock SHM 0 refid NMEA offset 0.300

        Restart Chrony, delete the log files.

        Even after performing the time "calibration" room temperature changes (I assume) cause it to drift around +/- 50ms.

        Rig Control

        I like Flrig, it gives you nice on screen control of most rig functions, digi mode apps connect using the Flrig option over a TCP port (e.g. default port).

        Flrig is also used with a shell script (below) to monitor for and recover from rig control errors caused by vehicle starts cutting power to the rig for a few seconds.

        sudo apt-get install flrig

        This installs an older version 1.4.7, Debian testing repo appears to have the current version, or compile it from source. To keep things simple I just use 1.4.7 from the Debian stable repo.

        Configure > Xcvr
        Rig IC-7100
        Baud 19200 (Set IC-7100 to match in Set > Connections > CI-V)

        Config > UI > Smaller Sliders
        Config > Restore > Use xcvr data checked, uncheck everything else

        Flrig can also sync the clock in the radio, Show/Hide controls (down arrow bottom left) > Misc

        Digi Mode Apps

        Only JS8Call and JS8CallUtilities_V2 are needed for the APRS stuff.

        The packages downloaded and installed below are for Debian.

        Correctly setting the audio levels see the WSJT-X Audio Levels section in MacLoggerDX + Flrig with WSJT-X, Fldigi, JS8Call. This setup process only needs to be done once using any digi mode app's tune command.

        Basically adjusting the USB MOD level and OS sound card mixer levels so that with the rig RF power set to 100% and the slider is at the top in WSJT-X or JS8Call you have 100% power output with no ALC action. We should not be pulling the slider down in the app to meet that goal, it means something else is set too high in the audio chain, which can be a source of IMD.


        Get js8call_2.2.0_20.04_amd64.deb from

        sudo dpkg -i js8call_2.2.0_20.04_amd64.deb

        If there is an missing dependencies error:

        sudo apt-get install -f
        sudo dpkg -i js8call_2.2.0_20.04_amd64.deb

        Settings > Radio > Rig: FLrig
        CAT Control > Network Server:
        Rig Options > PTT CAT, Mode Data/pkt, Split Operation Fake it, Hold PTT between frames.


        Now the magic part, some software to glue it all together and send updated positions via JS8Call.

        Mark M0IAX created an app written in Python called JS8CallUtilities_V2.

        This can be configured to automatically start with the TX timer enabled, Auto TX Grid to APRSIS enabled, and the position precision increased to 5, which sends fairly precise 10 character grid squares.

        For this to work, in JS8Call:
        • Enable the UDP API options in JS8Call under Settings > Reporting.
        • Enable Auto reply at startup under Settings > General > Networking & Autoreply.
        • Disable Idle timeout under Settings > General > Networking & Autoreply.
        • Settings > Radio > Rig Options > Hold PTT between frames. I don't see a use having the rig go back to receive for 2 seconds between frames

        Revisiting this in Feb/2024 on a Debian 12 (Bookworm) system I was unable to get v2 working (possibly related to having to setup an Python venv for the pip3 modules).

        I was able to get the compiled binary version from (Ubuntu2004) to run no problem.

        Download, unzip, run the binary, open Settings, configure GPS settings (GPSD), update the precision to 5 which sends a fairly precise 10 character grid (or not if you want to be less accurate), set the other options as needed. Save.

        Script to handle start up and power disruptions

        Vehicle stop/start causes the rig to turn off and back on again, which causes Flrig to lose rig control.

        Startup and monitor script
        PowerShell script for Windows use - flrig_aprs_start.ps1.

        This starts Flrig, JS8Call, and JS8CallUtilities, then monitors Flrig for rig control errors (radio off). When rig control error is detected it closes down the applications and waits for the rig's USB port to come back (indicating it has power again) then restarts the applications.

        This is done by monitoring the receiver DBM value from Flrig, -127 or higher is normal. If it goes to -128 rig control is lost, this is how it works with my Icom rigs.

        If JS8CallUtilities options are configured to automatically start sending the position reports to JS8Call for transmission when started, everything resumes in a running state with out intervention.

        Testing it out..

        Where on the waterfall / Hz offiset should be used? I use 2500 Hz which is above the general chat area. 

        To avoid the TX audio passing through the filter edges, enable Settings > Radio > Rig Options > Split Operation (Fake it works well with Icom rigs). JS8Call will shift the VFO and recalculate the offset on the fly so the TX audio is centered in the filters. Another option with out using Split Operation would to set the offset to 1500 Hz, and the rig VFO one kHz higher so it ends up at 2500 Hz.

        Sending a position report every 3 minutes, fairly good track from a test (

        HF APRS Mobile track via JS8

        Stations which heard my 20m mobile during test - 50W into a 20m Hamstick (

        HF APRS Mobile via JS8 PSKr reports

        I decided 20m was the better band choice for now, increased solar cycle 25 activity results in good propagation during daytime and into the evening and night. A 20m hamstick matched with an un-un will cover most of the band which gives the option of SSB/voice further up the band.

        40m may be a better choice at night when D-layer absorption is not a limiting factor, and during solar minimums during the day time where it might out perform 20m. At 40m the bandwidth of a hamstick becomes quite narrow (due to the amount of loading needed) limiting operation to a small segment with the digi modes which is a trade off.


        Maybe we get bored somewhere and want to work some digi mode DX for fun, or even put a 6m antenna on and activate a rare grid for the 6m grid chasers.

        Stable version is currently 2.7.0-rc3

        Get wsjtx_2.7.0-rc3_improved_PLUS_LINUX_amd64.deb from 

        sudo dpkg -i wsjtx_2.7.0-rc3_improved_PLUS_LINUX_amd64.deb

        If there is an missing dependancies error:

        sudo apt-get install -f
        sudo dpkg -i wsjtx_2.7.0-rc3_improved_PLUS_LINUX_amd64.deb


        Fldigi supports a number of digi chat modes. 

        sudo apt-get install fldigi

        Configure the waterfall level (bottom bar > upper signal level) so its visible, and the TX level (bottom bar), if the levels are setup correctly, -3 dB should be 50% RF output power.

        Raspberry Pi Automated Startup

        In 2020 I had originally planned on using a Raspberry Pi, and wanted it auto start the applications when it was powered on and boots. I put together a couple scripts to do this, see which includes some partly outdated setup info for the previous version of JS8CallUtilities.

        The missing part is having the Pi power on and off as needed


        For some time I've been intrigued with APRS over HF, while the VHF APRS system is very good, and easy to use with modern rigs like my Kenwood TH-D72A you're limited to being in range of an iGate or digipeater - normally not a problem in most populated places, and even many sparsely populated places.

        When I drove from Fairbanks Alaska to Seattle in May 2014, I ran VHF APRS with a 50W rig and decent antenna on the car, with a couple of exceptions (Tok AK and Whitehorse YT) once I was out of range of the digipeater in Fairbanks the coverage was non-existent until I was half way through British Columbia where the coverage was excellent all the way to Seattle. During the trip I shared the tracking link on with friends, and some of them got a real kick out of watching my trip progress on a map each day, including a couple goofups I made with wrong turns, one where I had to back the car with trailer back down a street the GPS "thought" looped around, but was a dead end.

        APRS on HF? There have been a few flavors around from what I have been able to find, 300 baud packet on 30m, and PSK63 (now defunct) were the main two. There is also now APRS over VARA but it seems more complex to setup and requires a dedicated monitoring station as well.

        JS8Call overall seems to be the best choice. The functionality is built in, every station running JS8Call is a monitor, and JS8 is based on FT8 with all of its weak signal and narrow bandwidth advantages.