MHSave and Python

Today I am playing with Python and Matplotlib. In BPQ32 you have the option to save the Most Heard list (MH) when you close BPQ32. This contains a lot of data that you can use. Above I made a plot of the received stations and the number of packets I received at 14.1022Mhz + 1000Hz at 300Baud. Now I am not a world programmer, so this could probably be easier or different. Below the script I have written and used.

import re, csv, zlib
import matplotlib.pyplot as plt
import numpy as np

#First get the data form the right port. 14.1022Mhz 300 Baud HF Packet

port4 = []

with open("MHSave.txt") as f:
        found_port4 = False

        for line in f:
                if line.startswith("Port:4"):

                        found_port4 = True

                if found_port4:
                        if line.startswith("Port:5"):
                                mod_string = line.replace('||', '')
                                mod_strings = re.sub("via.*$", "", mod_string)

with open('port4.txt', 'w') as fout:


# Convert it to a csv file
with open('port4.txt', 'r') as in_file:
    lines =
    stripped = [line.replace(","," ").split() for line in lines]
    grouped = zip(*[stripped]*1)
    with open('port4.csv', 'w') as out_file:
        writer = csv.writer(out_file)
        writer.writerow(('Epoch', 'Pack-rev', 'Call', 'Month', 'Day', 'Time'))
        for group in grouped:

# Matplotlib create a nice Plot of the received calls

filename = 'port4.csv'
with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)

    #Get Packets and Calls received
    packs, calls = [], []
    for row in reader:
        pack = int(row[1])
        call = str(row[2])

x = np.arange(len(calls))

fig, ax = plt.subplots()

ax.barh(x, packs, align='center')
ax.set_title("Call and Packets received on PI1LAP")
ax.set_xlabel('Received Packets')
ax.set_ylabel('Station Callsigns')
ax.set_xticks(packs, minor=True)

Kantronics KPC4

Today I have been working on a Kantronics KPC4 which I bought from PD4R. I am very happy that I can add it to the collection.

Kantronics KAM_KPC-1-2-4-2400_Installation Manual
Kantronics KAM_KPC-1-2-4-2400_Operations Manual

Kantronics KPC4 Firmware

The nice thing is that such modems can also be accessed from BPQ32. Here is a small example.

 ID=Serial TNC KPC4

Bpq32 with QtSoundModem and Hamlib

Yesterday I added 2 HF ports to my Bpq32 Node / BBS. I have chosen to use QtSoundModem and Hamlib. QtSoundModem is a Linux port or Soundmodem from UZ7HO. I use Hamlib/rigctld to take control of the Tranceiver. QtSoundmodem and Hamlib run on a different Raspberry than the BBS and Node.

After some testing I found out that I need Hamlib version 3.3 to control the icom 7300. The versions 4.0 and 4.1 do not work for me. Apparently the icom 7300 is not being initialized. Can’t actually find out why this is. With the command “rigctld -l” you get a list of which tranceivers are supported.

So I need number 373 for the Icom 7300.

/usr/local/bin/rigctld -m 373 -r /dev/ttyUSB0 -s 19200 -T -t 4532 &

In the QtSoundModem.ini I have in the [Init] section.


Now the bpq32.cfg

 ID=14.1022 +1100Hz
  ADDR 8101 ; AGW port of QtSoundModem

 ID=14.1022 +2000Hz
  ADDR 8101 ; AGW port of QtSoundModem

With Hamlib it is also possible to control the TRX from Bpq32. I immediately added a Robust 300 packet port to Bpq32 with rig control. Here is an example.

 ID=Robust 300 ;(RPR Packet)
WL2KREPORT PUBLIC,, 80, PI8LAP-10, JO11VN, 00-23, 14102200, ROBUST, 25, 35, 3
WL2KREPORT PUBLIC,, 80, PI8LAP-10, JO11VN, 00-23, 14102200, PKT300, 25, 35, 3
WL2KREPORT PUBLIC,, 80, PI8LAP-10, JO11VN, 00-23, 144850000, PKT1200, 10, 20, 5, 0
WL2KREPORT PUBLIC,, 80, PI8LAP-10, JO11VN, 00-23, 430950000, PKT9600, 10, 20, 5, 0
  O 4                   ; MAXFRAME
  F 190                 ; FRACK
  T 8                   ; TX Delay
  USEAPPLCALLS          ; Accept connects to all APPLCALLS
  BEACONAFTERSESSION    ; Beacon after session
  %L 1500               ; Centre Freq for Normal Packet (Default is 1500)
  @I 64                 ; Paclen = 60
  %T 1                  ; TX Autotracking 1 = on
  %N 10
  %B 300


Apr  4 16:34:41 pi1lap : Initialising Port 01     TCPKISS IP Port 8001 Chan A
Apr  4 16:34:41 pi1lap : Initialising Port 02     TCPKISS IP Port 8001 Chan B
Apr  4 16:34:41 pi1lap : Initialising Port 03     SCSTRK /dev/ttyUSB0
Apr  4 16:34:41 pi1lap : Initialising Port 04     UZ7HO Host Port 8101 Chan A
Apr  4 16:34:41 pi1lap : Initialising Port 05     UZ7HO Host Port 8101 Chan B
Apr  4 16:34:41 pi1lap : Initialising Port 06     ASYNC /dev/ttyUSB1 Chan A


Aprs Weather Beacon

Today I’ve been messing around with an APRS weather beacon. Now Direwolf and Linbpq and Jnos can send an aprs weather beacon. It turns out that this is quite precise, with the format of the beacon.

# The weather beacon have to look like this....
# @220424z5057.81N/00729.37E_094/002g005t043r000p006P006h89b09783
# !5133.52N/00348.15E_073/013g...t048h85b10040wWXD
# Jun 01 2003 08:07
# 272/000g006t069r010p030P020h61b10150
# ***********************************************************
# 272 - wind direction - 272 degrees
# 010 - wind speed - 10 mph
# g015 - wind gust - 15 mph
# t069 - temperature - 69 degrees F
# r010 - rain in last hour in hundredths of an inch - 0.1 inches
# p030 - rain in last 24 hours in hundredths of an inch - 0.3 inches
# P020 - rain since midnight in hundredths of an inch - 0.2 inches
# h61 - humidity 61% (00 = 100%)
# b10153 - barometric pressure in tenths of a MILLIBAR - 1015.3 MILLIBARS

My weather station uploads its data to Now wunderground has the option to read this again with an api key.

You can read here how and what.

After a lot of messing around with a bash script, I am able to create the correct format.

TEMP=-4.9°C Temperature degrees Celsius
WPK=29.4km/h Wind speed in Kilometers per hour
WGK=39km/h Wind guts in Kilometers per hour
GRD=58° Wind direction in degrees
RAIN=0mm Rain in the last hour in mm
RAIN24=0.42065mm Rain in the last 24 hour in mm
RAIN12=0.214mm Rain in the last 12 hour in mm
HUM=74% Humidity in procent
Bar=1004mb Barometric pressure in millibars
FAH=023F Temperature degrees Fahrenheit
WPM=018mph Wind speed in miles per hour
WGM=024mph Wind guts in miles per hour
RNI=000inch Rain in the last hour in inches
RNI=001inch Rain in the last 24 hour in inches
RNI=000inch Rain in the last 12 hour in inches

The file I need to broadcast an APRS Weahter Beacon looks like this.

pd9q@pancake:~/linbpq/wx-project $ cat ~/linbpq/current.txt
Feb 09 2021 13:00

The config file for Linbpq looks like this, this is in the aprs section of bpq32.cfg

WXComment=/Weather Station JO11VN
WXPortList=1,5,IS        ; comma separated list 
WXInterval=10            ; mins

For Jnos in the autoexec.nos in the aprs section

aprs wx call PD9Q-7
aprs wx stat "Weather Station JO11VN"
aprs wx pos "5133.52N/00348.15E_METEO
aprs wx data "/home/pd9q/jnos/wx/current.wx"
aprs bc rftimer 10

For direwolf in the file direwolf.conf

PBEACON LAT=51^33.52N LONG=03^48.15E SYMBOL=”weather station” COMMENTCMD=”tail -1 /home/pd9q/linbpq/current.txt”

Direwolf Aprs packet look like this.


BPQ32 Aprs packet look like this.

0h75b10007/Weather Station JO11VN

Learned a lot.

BPQ32 Yapp file transfer

BPQ32 and QTermTCP support the Yapp Protocol. Let’s take a look at how that works.

First we have to great a Directory  ” Files”  in the root dir of Linbpq. The user Pi must be the owner of the Directory.

cd /home/pi/linbpq
mkdir Files
ls -l
drwxr-xr-x 2 pi pi    4096 nov  1 12:10 Files
* If the user Pi does not own the directory "Files", you can change that with.
sudo chown pi:pi Files

Now we can set QTermTCP to use the directory “Files” for uploads and downloads. In the top menu choose ” Yapp” , ” Set Receive Directory” and choose the correct directory (Files).

First we need to connect to a local BBS that supports the YAPP protocol. Now I have set up a BBS here for this test. As modems I use two Ninotnc`s connected with a null modem cable.
Now we are ready to send a file. Again choose in the top menu “Yapp” and “Send File” Now you can choose which file you want to send.

Here we go…..

Monitor screen from Linbpq BBS.

File compleet.

The same file but compressed.

NinoTnc progress

Boy, I can hit my head against the wall. I made a very rookie mistake. I had  soldered a number of Leds the wrong way round.  Tsss before I finally invented that. Very stupid.
But when I finally found out (it’s even in the description on the tarpn website) it now works the way it should.

Let’s test how the reception is. (aprs on 144.800Mhz @ 1200 Baud)

I feel like he is a little deaf. Looks like he’s missing some frames. Maybe it’s the setup I’m using. I am using a Yaesu ft7800 with the NinoTnc directly on the Mini Din of the radio. I have to figure this out, I will read the Tarpn website one more time.

First let’s update the flash.

Mmmmm, let’s give it a go.


A Linbpq configuration example



I am very happy to be able to add this (Nino)TNC to the collection.

Linux Port of UZ7HO’s Soundmodem

Very good news, John G8BPQ has ported Soundmodem from UZ7HO to Linux.

Mail from John G8BPQ.

Andy UZ7HO has allowed me to port his Soundmodem to C so that it can be run run Linux systems. See

This is pre-Beta software. It has been tested by several people but is likely to still have bugs.

John G8BPQ

Guide…BPQ User and Sysop Commands

Bill PY2BIL has wrote a great guide with Sysop and User commands.

PY2BIL wrote,

Since I started with my BPQ BBS I was looking for an easier way to access the documentation and find what I needed at the moment, so as many do, I wrote down what I used the most along the way. Recently I decided to take the plunge and write the ‘Official BPQ Cheat Sheet’ (hihi) based on the official documentation that would make my life easier. Some of the commands I found in the documentation are flagged as obsolete or no other reference was found and I suspect that many changes that John did are still not formally documented and may be laying around in this forum.

The official website,

Or download it from this link.

Thanks Bill great document.

Update Linbpq with up2bpq

Ok, first of all I want to apologize for my fantastic bash scripting arts. There must be people laughing there ass off.

I was searching the internet for an update program or script for Linbpq. I could not find these, so I started using my bash scripting skills.

Maybe someone has better ideas.

The problem is that John GM8BPQ does not work with version numbers in his program names. This makes it difficult to quickly see if you need to update. Now I always look at the dates, this gave me an idea.

Why not look at the Last_Modified date with a shell script. Now of course you first have to check on your own system which date you have with your most recent Linbpq program file.

pd9q@packet:~ $ date -d "$( stat /home/pd9q/linbpq/linbpq | awk '/Modify/{gsub( /^[^:]+: +/,"",$0); print}' )"   "+%Y-%m-%d"

Okay now we have to take a look at John’s date on his web server.

pd9q@packet:~ $ date -d "$( curl -sI  | awk '/Last-Modified/{gsub( /^[^:]+: +/,"",$0); print}' )"   "+%Y-%m-%d"

Now you have two dates, lets compare.

local=$(date -d "$( stat /home/pd9q/linbpq/check/linbpq | awk '/Modify/{gsub( /^[^:]+: +/,"",$0); print}' )"   "+%Y-%m-%d")
remote=$(date -d "$( curl -sI  | awk '/Last-Modified/{gsub( /^[^:]+: +/,"",$0); print}' )"   "+%Y-%m-%d")
    # Compare the Modified date`s
if (( ${local//-/} < ${remote//-/} ));

It should be  “if (( ${local//-/} < ${remote//-/} ));”

The local file is from 2019-09-26 and de remote file is from 2019-10-05
Let get the new Linbpq version from 2019-10-05 and downloading it with a timestamp. I want the timestamp to remain the same, otherwise nothing later can be compared.

wget -N -P /home/pd9q/linbpq

The -N oprions by the wget command stands for –Timestammping

Now I want to name the file linbpq with the date of the download and copy it to the directory /home/pd9q/linbpq. If you use the -p option with cp the timestamp stays the same. And I also have the file in the /home/pd9q/linbpq/check directory. This is because I need it to compare the dates.

now=$(date "+%Y-%m-%d")
    cp -p /home/pd9q/linbpq/pilinbpq /home/pd9q/linbpq/linbpq-$now
    yes | cp -rfp /home/pd9q/linbpq/pilinbpq /home/pd9q/linbpq/check/linbpq

Let`s remove pilinbpq, we no longer need him. And chmod the linbpq file so we can execute it.

rm -f /home/pd9q/linbpq/pilinbpq
chmod +x /home/pd9q/linbpq/linbpq-$now

I’m using the sed command to alter the linbpq start file.

sed -i "s,sudo -u pd9q ./.*$,sudo -u pd9q ./linbpq-"$now"," /home/pd9q/linbpq/linbpq.start
pd9q@packet:~ $  grep linbpq-  /home/pd9q/linbpq/linbpq.start
sudo -u pd9q ./linbpq-2019-10-31

That works very well.

Now let’s restart Linbpq with the new version of Linbpq

sudo systemctl restart linbpq

If you now run up2bpq again you will get the following message if the two dates match.

pd9q@packet:~ $ ./up2bpq
Your version has the same timestamp so your version is up2date
The local linbpq in the /home/pd9q/linbpq/check directory has 2019-10-05 as timestamp.
The remote pilinbpq has 2019-10-05 as timestamp.

Here is the entire script.

# Fist make a directory called check in your linbpq directory and made a copy of the linbpq program file to it.
    # Lets get the Modify date from linbpq local en pilinbpq remote
local=$(date -d "$( stat /home/pd9q/linbpq/check/linbpq | awk '/Modify/{gsub( /^[^:]+: +/,"",$0); print}' )"   "+%Y-%m-%d")
remote=$(date -d "$( curl -sI  | awk '/Last-Modified/{gsub( /^[^:]+: +/,"",$0); print}' )"   "+%Y-%m-%d")
    # Compare the Modified date`s
if (( ${local//-/} < ${remote//-/} ));
    echo The local file is from $local and de remote file is from $remote
    echo Let get the new Linbpq version from $remote and downloading it with a timestamp.
    wget -N -P /home/pd9q/linbpq
    echo Let give the file a date.
    echo We are going to copy the file with the same Last_Modified as on the webserver of GM8BPQ.
    echo And we give it the timestamp of downloading. Dont forget to copy it with the -p option.
    now=$(date "+%Y-%m-%d")
    cp -p /home/pd9q/linbpq/pilinbpq /home/pd9q/linbpq/linbpq-$now
    yes | cp -rfp /home/pd9q/linbpq/pilinbpq /home/pd9q/linbpq/check/linbpq
    # Remove pilinbpq
    rm -f /home/pd9q/linbpq/pilinbpq
    chmod +x /home/pd9q/linbpq/linbpq-$now
    # We are going to use the sed command to alter the linbpq start file.
    sed -i "s,sudo -u pd9q ./.*$,sudo -u pd9q ./linbpq-"$now"," /home/pd9q/linbpq/linbpq.start
    echo Lets check "if" its was okay.
    grep linbpq-  /home/pd9q/linbpq/linbpq.start
    echo Now lets start Linbpq with the new version.
    sudo systemctl restart linbpq
    echo "Your version has the same timestamp so your version is up2date"
    echo The local linbpq in the /home/pd9q/linbpq/check directory has $local as timestamp.
    echo The remote pilinbpq has $remote as timestamp