Skip to content
Scripting the Kantronics KPC-3 Plus: Fill-in Digi, KISS, PBBS and Backups

Scripting the Kantronics KPC-3 Plus: Fill-in Digi, KISS, PBBS and Backups

The Kantronics KPC-3 Plus is a classic hardware TNC that still does a fine job as an APRS fill-in digipeater, a KISS modem or a small mailbox. Configuring it by hand, though, means a serial terminal, a 1990s manual and a long list of commands you have to get right every time.

So I wrote kpc3-tools: two small Python scripts that factory-reset the TNC and set it up for a given role with one command, and that back up and restore its full configuration. Everything here was tested on a KPC-3 Plus with firmware 8.3.

What you need

  • A KPC-3 Plus connected to a serial port (a USB serial adapter works fine, e.g. /dev/ttyUSB0)
  • Python 3 with pyserial
  • On Linux, access to the serial port (usually the uucp or dialout group)
git clone https://github.com/edufortes/kpc3-tools.git
cd kpc3-tools
pip install -r requirements.txt

One command per role

kpc3.py takes a mode, your callsign and the serial port:

Mode What it sets up
fillin WIDE1-1 fill-in digipeater, no beacon
fillin-beacon WIDE1-1 fill-in digipeater plus an APRS position beacon
kiss KISS mode for Dire Wolf, APRX, kissattach, Xastir…
pbbs Personal mailbox (PBBS)
show Print the current configuration, changes nothing
./kpc3.py fillin        DL7EDU-10 /dev/ttyUSB0
./kpc3.py fillin-beacon DL7EDU-10 /dev/ttyUSB0 --lat 50.1000 --lon 8.6800 \
    --comment "WIDE1-1 Fill-in Digi" --interval 30
./kpc3.py kiss          DL7EDU-10 /dev/ttyUSB0
./kpc3.py pbbs          DL7EDU-10 /dev/ttyUSB0 --pbbs-call DL7EDU-1

Each setup run does the same steps:

  1. Finds the TNC at whatever baud rate it is on. If it is in KISS mode it sends C0 FF C0 to get it out first.
  2. Runs RESTORE DEFAULT, sends * for the autobaud and answers the ENTER YOUR CALLSIGN=> prompt.
  3. Switches from the factory NEWUSER mode to TERMINAL and resets.
  4. Turns the transmitter off (XMITOK OFF), sets the clock and all the settings for the mode, then turns it back on.

Add --dry-run to see the commands without touching the TNC.

Every setup run starts with a factory reset. Take a backup first (see below).

The fill-in digipeater

These are the settings I use for a WIDE1-1 fill-in:

UIDIGI   ON WIDE1-1    only answer WIDE1-1
UIDWAIT  ON            UI repeats honour DWAIT
DWAIT    0             (--dwait)
DIGIPEAT OFF           no plain callsign/alias digipeating
HID      OFF           no ID packets
PBBS     0             the factory default enables a 100 KB PBBS
CD       SOFTWARE      (--cd)
MONITOR  ON
MRPT     ON

Two settings are worth explaining:

  • CD SOFTWARE: the factory default is CD INTERNAL. With software carrier detect the TNC considers the channel busy when it actually hears packet audio, not just noise.
  • DWAIT: there is no “viscous delay” on the KPC-3 Plus. DWAIT (with UIDWAIT ON) only delays the repeat, up to 2.55 s, but the packet is always repeated. A small value like --dwait 300 gives the wide-area digis a chance to go first. If you want a real viscous delay (hold the packet and drop it if another digi repeats it first), run the KPC in KISS mode behind APRX.

A proper APRS beacon

My first attempt used the usual BTEXT and BEACON EVERY 30. It worked, but looking at the monitor output I noticed my beacon went out as:

DL7EDU-10>BEACON: <UI>: !....N/.....E#WIDE1-1 Fill-in Digi

On the KPC, BTEXT beacons are always sent to the destination BEACON. UNPROTO only adds the via path. APRS still decodes it, but it is not clean.

The fix is the location-text beacon, which is what the script uses now:

BEACON EVERY 0
LT  1 !5006.00N/00840.80E#WIDE1-1 Fill-in Digi
LTP 1 APN383 VIA WIDE2-1
BLT 1 EVERY 00:30:00

LTP lets you set both the destination and the path, so the beacon now goes out as DL7EDU-10>APN383,WIDE2-1. It works without a GPS connected. The script builds the position string from decimal degrees:

./kpc3.py fillin-beacon DL7EDU-10 /dev/ttyUSB0 --lat 50.1000 --lon 8.6800 \
    --comment "WIDE1-1 Fill-in Digi" --interval 15 --path WIDE2-1 --symbol "1#"

To change only the beacon of a running digi, without a reset, add --beacon-only.

Backup and restore

kpcbackup.py saves the whole configuration to a text file and can load it back:

./kpcbackup.py backup  /dev/ttyUSB0
# saved backups/kantronics-KPC3P-8.3-2026-10-28.txt

./kpcbackup.py restore /dev/ttyUSB0 backups/kantronics-KPC3P-8.3-2026-10-28.txt

Firmware 8.3 has no VERSION command, so the backup does a soft RESET and reads the model and version from the startup banner. That is also what goes into the file name.

The restore is the interesting part. The DISPLAY output is not valid command syntax (FRACK 4 (4 sec), BEACON EVERY 30 min, MYALIAS disabled…). So the restore does a factory reset, reads the default values, and only sends the settings that differ, translated back into commands. It refuses to restore a backup from a different model or firmware unless you add --force.

I tested it as a round trip: backup, restore, backup again. The two files are identical, apart from the clock.

Firmware 8.3 quirks

Things I ran into while writing this, useful even if you configure the TNC by hand:

  • No VERSION command. The version only shows in the banner after RESET.
  • NEWUSER mode after a factory reset refuses some commands (XMITOK, for example) until you set INTFACE TERMINAL and RESET.
  • UIDUPE does not exist in 8.3; it came with firmware 9.x.
  • DWAIT maximum is 255, that is 2550 ms.
  • Clearing values is inconsistent. % clears most parameters (MYALIAS %, BTEXT %, LT 1 %), but GPSHEAD 2 % and CWIDTEXT % store a literal %. GPSHEAD 2 with no value clears it.
  • UIFLOOD % disables the alias but keeps the other fields.
  • CTRL A OFF B OFF is ignored. Send CTRL A OFF and CTRL B OFF separately.
  • Changing PBBS or MYREMOTE reboots the TNC.
  • Error messages vary: EH?, ?..., Input ignored, Value out of range, Command not available in NEWUSER mode.

References

73 de DL7EDU

Last updated on • Eduardo Fortes