As I continue to learn about digital modes and ham radio, I was intrigued with the idea of testing ax.25 vs ardop in real world situations. As it turns out, I had no idea what I was getting myself into! It was one of the most painful Linux setups that I’ve ever done, not because it was so terribly hard, but I did not fine one complete step by step document to guide me through it. It took me several days of fiddling and lots of research to get it sorted out. I’m putting it all together here, in hopes that it will help the next guy!

First, I needed to install direwolf and ax.25 utilities in Ubuntu:

  $ sudo apt-get update
  $ sudo apt-get install ax25-tools
  $ sudo apt-get install direwolf

Then, I had to create a system service to start and stop the ax.25 interface and reload the daemons:

  $ sudo nano /lib/systemd/system/ax25.service
  
  =======================
[Unit]
Description=AX.25 KISS interface
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/ax25-up /dev/ttyUSB0 wl2k 1200

[Install]
WantedBy=default.target

  =======================
  $ sudo systemctl daemon-reload

Next, I needed to download an ax.25-up binary and make it executable:


  $ sudo curl -o /usr/local/bin/ax25-up https://raw.githubusercontent.com/la5nta/pat/master/share/bin/axup
  $ sudo chmod +x /usr/local/bin/ax25-up 

Now I had to create virtual ports for ax.25 to use. Notice that since I am using HF, I needed a low baud rate (speed) of 300, rather than 1200, as you would expect to see with VHF/UHF.

  $ sudo nano /etc/ax25/axports 
  
   ======================= 
# /etc/ax25/axports
#
# The format of this file is:
#
# name callsign speed paclen window description
#

#1	OH2BNS-1	1200	255	2	144.675 MHz (1200  bps)
#2	OH2BNS-9	38400	255	7	TNOS/Linux  (38400 bps)

#portname       callsign        speed   paclen  window  description
wl2k            KL4TH           300     255     7       Winlink

  ======================= 

Now I can start and stop the ax.25 service, or check the status at will, like so:

  $ sudo systemctl start ax25
  $ sudo systemctl status ax25 -l
  $ sudo systemctl stop ax25
  $ sudo systemctl start ax25

After that I edited my PAT configuration file. Notice in the PAT configuration file that the ax.25 port of wl2k matches the axport portname that we made earlier:

  $ pat configure
  
  =======================
  {
  "mycall": "KL4TH",
  "secure_login_password": "<EDITED>",
  "auxiliary_addresses": [],
  "locator": "BP64du",
  "service_codes": [
    "PUBLIC"
  ],
  "http_addr": "localhost:8080",
  "motd": [
    "Open source Winlink client - getpat.io"
  ],
  "connect_aliases": {
    "telnet": "telnet://{mycall}:CMSTelnet@cms.winlink.org:8772/wl2k"
  },
  "listen": [],
  "hamlib_rigs": {"myrig": {"address": "localhost:4532", "network": "tcp"}},
  "ax25": {
    "port": "wl2k",
    "beacon": {
      "every": 3600,
      "message": "Winlink P2P",
      "destination": "IDENT"
    },
    "rig": ""
  },
  "serial-tnc": {
    "path": "/dev/ttyUSB0",
    "baudrate": 4800,
    "type": "Yaesu"
  },
  "winmor": {
    "addr": "localhost:8500",
    "inbound_bandwidth": 1600,
    "drive_level": 0,
    "rig": "",
    "ptt_ctrl": false
  },
  "ardop": {
    "rig": "myrig",
    "ptt_ctrl": false,
    "addr": "localhost:8515",
    "arq_bandwidth": {
      "Forced": false,
      "Max": 500
    },
    "beacon_interval": 0,
    "cwid_enabled": true
  },
  "pactor": {
    "path": "/dev/ttyUSB0",
    "baudrate": 57600,
    "rig": "",
    "custom_init_script": ""
  },
  "telnet": {
    "listen_addr": ":8774",
    "password": ""
  },
  "gpsd": {
    "enable_http": false,
    "use_server_time": false,
    "addr": "localhost:2947"
  },
  "schedule": {},
  "version_reporting_disabled": false,
  "forms_path": "/home/alaskalinuxuser/.wl2k/Standard_Forms"
}
  =======================
  
  

Before I could start direwolf, I needed to define a few things in the config file. There file is huge, and I didn’t change too much, the rest I left as default. This file can be downloaded here, and you put it in your home folder as ~/direwolf.conf making the necessary edits:

#############################################################
#                                                           #
#               FIRST AUDIO DEVICE PROPERTIES               #
#               (Channel 0 + 1 if in stereo)                #
#                                                           #
#############################################################

# Get this with aplay -l
ADEVICE plughw:1,0

#
# Number of audio channels for this souncard:  1 or 2.
#

ACHANNELS 1

#############################################################
#                                                           #
#               CHANNEL 0 PROPERTIES                        #
#                                                           #
#############################################################

CHANNEL 0

MYCALL KL4TH-0

MODEM 300

#############################################################
#                                                           #
#               VIRTUAL TNC SERVER PROPERTIES               #
#                                                           #
#############################################################


AGWPORT 8000
KISSPORT 8001

Then I could start direwolf with sudo, because it didn’t work right without using sudo:

$ sudo direwolf -t 0 -p
  
Dire Wolf version 1.5
Includes optional support for:  gpsd hamlib

Reading config file direwolf.conf
Audio device for both receive and transmit: plughw:1,0  (channel 0)
Channel 0: 300 baud, AFSK 1600 & 1800 Hz, D, 44100 sample rate / 3.
Note: PTT not configured for channel 0. (Ignore this if using VOX.)
Ready to accept AGW client application 0 on port 8000 ...
Ready to accept KISS TCP client application 0 on port 8001 ...
Virtual KISS TNC is available on /dev/pts/5
Created symlink /tmp/kisstnc -> /dev/pts/5

With direwolf running, we can see the created symlink to /dev/pts/5 (in this case), and we can use that with kissattach to link the dev port to our axport. Keep in mind, you have to launch this with sudo, or it will not work!

$ sudo /usr/sbin/kissattach /dev/pts/5 wl2k
  
AX.25 port wl2k bound to device ax0

Of course, I also needed rig control, so I launched that as usual with rigctrld:

$ rigctld -m 105 -s 4800 -r /dev/ttyUSB0

Finally, we are ready to start PAT and listen on ax.25:

$ pat --listen "ax25" http

Now when I open up my browser, pointed to localhost:8080, I get the usual PAT interface with the “listening on ax.25” banner at the top!

All in all, it is much more complicated to use and setup than ardop, by far. However, it was supposed to be faster and more robust from the studies I reviewed. Unfortunately, I couldn’t put that to a test, as the nearest station using HF and ax.25 was 700km away, and I couldn’t get it to connect. Likewise, with ardop, I couldn’t connect to anyone that far away either, so I didn’t conclusively prove anything.

Linux – keep it simple.

4 Replies to “Pat, Winlink, and AX.25”

  1. Good stuff. I live on Vancouver Island and I came across this as it is exactly the setup I am attempting except for the radio model. I do have a question. I saw the line
    “hamlib_rigs”: {“myrig”: {“address”: “localhost:4532”, “network”: “tcp”}

    Where does the port 4532 come from?
    Same goes for the Telnet port.
    I should be able to test this here in HF bands as I can hit a few at 40 and 80 meters. Where did you learn of the options that are in the configuration? That is how I ended up here, I was looking for anything that might explain the settings in the pat config file.

    1. Good questions, I will tackle them one at a time, but in a slightly different order. 😀
      The Telnet port can be set to anything that is valid, but for “telnet”: “telnet://{mycall}:CMSTelnet@cms.winlink.org:8772/wl2k” the official winlink server, they have set their server to listen on port 8772, so if you choose a different port, you will not connect to them.
      If you want to telnet to someone else with PAT, you will need to know what telnet port they are listening on.

    2. Part two: “hamlib_rigs”: {“myrig”: {“address”: “localhost:4532”, “network”: “tcp”}

      Where does the port 4532 come from?

      When you run rigctld, the default port number is 4532. You can set it to anything you want with the -t command:
      -t, –port=number
      Use number as the TCP listening port.
      But, the default is 4532. So that line in PAT is using the default port for rigctld. You should only change it in PAT if you also change it in rigctld.

    3. And finally, I might also recommend TNC attach rather than ax.25, as it is much easier to implement. My post here is from 2021 – 3 years ago. I have a newer writeup where I use it to connect to computers and do telnet: https://alaskalinuxuser3.ddns.net/2024/09/24/taking-the-roophloch-challenge/
      And at the bottom of that are some more links to use it, and some videos by others. I now use TNCattach with PAT to do winlink, and it works flawlessly and is much simpler to set up in PAT.
      This writeup will be most helpful for you:
      https://kc3smw.net/2023/07/14/pat-winlink-on-linux/

Leave a Reply

Your email address will not be published. Required fields are marked *