Packet Radio on Debian 9 with Direwolf and ax25

I’ve played around with Packet and Direwolf on the Raspberry Pi quite a bit, but every time I try and getting it working on Linux on a desktop I run into some differences in the config. From past attempts, I followed most of the steps I had followed before here.

The following steps are with a USB Rigblaster Plug n Play, connected to the dataport on my Icom 880h radio .

I installed and compiled Direwolf from source as before, and started it up with:

$ direwolf -t 0 -p
Dire Wolf version 1.5
Reading config file direwolf.conf
Audio device for both receive and transmit: plughw:0,0 (channel 0)
Channel 0: 1200 baud, AFSK 1200 & 2200 Hz, E+, 44100 sample rate.
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/1
Created symlink /tmp/kisstnc -> /dev/pts/1

I installed the ax25 apps as in the previous article, and then added 1 line to /etc/ax25/ports:

1    KK6DCT-1    1200    255 2   2m packet

I then started kissattach:

$ sudo kissattach /dev/pts/1 1

/dev/pts/1 is the value from when Direwolf started, and port 1 is the line I added to the ports file.

From here I can connect to the local ag6qo-1 BBS, via the BERR37 node:

axcall 1 ag6qo-1 via berr37

Building an Amateur Radio Packet to Twitter bridge: Part 3 – preventing duplicate tweets

In my last post (part 2, also see part 1 here), I talked about Twitter’s API rate limits. Since many Packet Radio transmissions are duplicates by their nature, for example, beacon packets and ID packets, it’s important to have some kind of mechanism to prevent sending these through to Twitter.

The approach I used was to insert each received packet into a MongoDB database, storing the received packet data, who the packet was from and who to, and additional metadata about the packet, for example, when last sent, and when it was last received.

Here’s an example of what each document stored looks like:

{
 "_id" : ObjectId("5909828e5a2f130fc8039882"),
 "firstHeard" : ISODate("2017-05-03T07:11:10.051Z"),
 "from" : "AE6OR ",
 "heardTimes" : 1,
 "infoString" : "Ф¤@à–¤ˆŽ@@à–„Š¤¤@ஞžˆ²@`–„Ѝ@`¨‚žŠ@a\u0003ðHello from 5W Garage packet node AUBURN 73's Steli !\r",
 "lastHeard" : ISODate("2017-05-03T07:11:10.051Z"),
 "lastTweet" : ISODate("2017-05-03T07:11:10.051Z"),
 "to" : "BEACON",
 "tweet" : "Received station: AE6OR  sending to: BEACON : Ф¤@à–¤ˆŽ@@à–„Š¤¤@ஞžˆ²@`–„Ѝ@`¨‚žŠ@a\u0003ðHello from 5W Garage packet node AUBURN 73's Steli !\r"
}

My current logic to check for duplicates and record when a tweet is last sent is:

    1. search for a matching document (tweet details) with a $lt condition that lastTweet is before ‘now – 12 hours’:
      document.lastTweet = {'$lt' : moment().utc().subtract(12, 'hours').toDate() };
    2. This is executed as a findOne() query:
      db.collection('tweets').findOne(document).then(function (olderResult) {
         ...
      }
    3. If an existing document older than 12 hours is found, then update properties to record that this same packet was seen now, and the time is was resent was also now (we’ll resend it to the Twitter api after the db updates):
      if (olderResult != null) {
          sendTweet = true;
          updateProperties = {
              lastHeard: now,
              lastTweet: now
          };
      }
      else {
          updateProperties = {
              lastHeard: now
          };
      }

      If not older than 12 hours, set properties to be updated to indicate just the lastHeard property

    4. To either update the existing document or insert a new document if this was the first time this packet was heard, do an ‘upsert’:
      db.collection('tweets').update(
          document,
          {
              $set: updateProperties,
              $inc: {heardTimes: 1},
              $setOnInsert: {
                  firstHeard: now,
                  lastTweet: now
              }
          },
          {upsert: true}
      ).then(function (response) {
      ...
      }
    5. Depending on the result indicating if we inserted or updated, set a property so on return we know whether to send a new Tweet or not:
      if(response.upserted != null || sendTweet) {
          response.sendTweet = true;
      }
      else{
          response.sendTweet = false;
      }

The approach is not yet completely foolproof, but it is stopping the majority of duplicate Tweets sent to Twitter so far.

For the full source check the project on github here: https://github.com/kevinhooke/PacketRadioToTwitter .

Packet Radio with Debian Hamradio Pure Blend

I stumbled across this concept of ‘Debian Pure Blends‘ a couple of days back. These are Debian distros that are configured with software preinstalled for a specific purpose, like graphic design, and astronomy. The Ham Radio distro caught my eye as it’s preconfigured with ax25 and Direwolf for Packet Radio.

The trouble is, while it has these included in the distro so you get them out of the box, it doesn’t seem they’re configured, and worse, the ax25 support doesn’t appear to work with Direwolf.

Here’s a few notes of my experimenting:

Direwolf uses a direwolf.conf file in your home directory which you customize with your callsign and setup to connect with your soundcard input and output. There doesn’t seem to be a copy of this file anywhere on the filesystem. The file is usually created if you’re building/installing from source by running ‘make install-conf’. I searched my fresh Debian install and couldn’t find a copy of direwolf.conf anywhere, so already being familiar with Direwolf, I decided to uninstall the pre-installed version (apt-get remove direwolf) and build/install from source unstead. See my previous notes on how to do this.

Immediately ran into the libasound library missing:

/usr/bin/ld: cannot find -lasound
 collect2: error: ld returned 1 exit status
 Makefile.linux:257: recipe for target 'fsk_fast_filter.h' failed
 make: *** [fsk_fast_filter.h] Error 1

This is fixed by installing libasound:

apt-get install libasound2-dev

 

Edit /etc/ax25/axports and add a line like this:
1 YOURCALL-1 1200 255 2 2m packet

Starting up direwolf for the first time:

 kev@kh-debian:/etc/ax25$ direwolf -t 0 -p
 Dire Wolf version 1.3

Reading config file /home/kev/direwolf.conf
 Audio device for both receive and transmit: default (channel 0)
 Channel 0: 1200 baud, AFSK 1200 & 2200 Hz, E+, 44100 sample rate.
 ERROR can't open device /dev/ttyUSB0 for channel 0 PTT control.
 Permission denied
 Note: PTT not configured for channel 0. (Ignore this if using VOX.)
 Ready to accept KISS client application on port 8001 ...
 Ready to accept AGW client application 0 on port 8000 ...
 Virtual KISS TNC is available on /dev/pts/1
 WARNING - Dire Wolf will hang eventually if nothing is reading from it.
 Created symlink /tmp/kisstnc -> /dev/pts/1

Looks like /dev/ttyUSB0 cannot be opened for my PTT on my Rigblaster Plug n Play.

Following instructions from here, as root, I did:

usermod -a -G dialout kev

and then logged out and logged back in again. That fixed that issue.

The input volume was low, so I bumped up the mic slider in the top right to about half way, and now the input volume is better:

KG6SJT-10 audio level = 43(20/19) [NONE] |||||||__
 [0.3] KG6SJT-10>ID:Network Node (YCARES)
 Unknown message type N, motorcycle

 

Next up, starting Direwolf and then starting up my ax25 stack with kissattach and mkiss (which I’ve covered before here), I was getting a Permission Denied error:

kev@kh-debian:~$ sudo kissattach /dev/ptmx 1 44.56.4.118
AX.25 port 1 bound to device ax0
Awaiting client connects on
/dev/pts/4

Followed by:

kev@kh-debian:~$ sudo mkiss /tmp/kisstnc /dev/pts/4
 mkiss: open: Permission denied

I posted a question about this on the Direwolf group on Yahoo Groups here. Since it looks like mkiss is getting permission denied accessing /tmp/kisstnc from Direwolf, I started Direwolf with a sudo and this avoided this error. Direwolf shouldn’t need to run with sudo permissions so something’s not quite right, but this did allow me to get up and running, and then I could ‘axcall 1 kberr’ to make a connection to nearest packet node.

To get to this point I could have installed a vanilla version of Debian, Direwolf from source, and ax25, and I probably would have got to the same point in about the same about of time, but when I have time I’ll take a look at the other apps that get preinstalled.

Winlink amateur radio email via paclink-unix on the Raspberry Pi

This is my second attempt to get a Winlink client (see here for a high level overview of Winlink) working on the Raspberry Pi. I first tried Pat /wl2k-go but it crashed (I created a ticket on github to followup), so for my second attempt I took a look at paclink-unix.

This site has a very detailed step by step install and config steps – follow exactly and pay attention to any errors 🙂 : http://bazaudi.com/plu/doku.php?id=plu:install_plu

A few additional notes:

  • wl2kax25 did not compile for me with the ax25 version that I previously had installed, possibly from apt-get from the default repos. Once I noticed this was missing I went back to the steps in the doc above and downloaded the ax25 packages from source, compiled, installed, rebuilt paclink and now I had the wl2kax25 app
  • Editing the /usr/local/etc/wl2k.conf file: the email= value is your local user email address on your local device, in this case on the Pi (e.g. for me, pi@localhost). This is used when wl2ktelnet/wl2kax25 retrieves incoming messages and it sends them to this user. If you see the wl2k app downloading messages but they’re not showing up in your inbox, check this.
  • Checking /var/log/mail.log is very useful to see what’s happening to your outbound and inbound messages!

The usage sequence is:

  • send outbound message with mail client, e.g. alpine
  • run wl2ktelnet to send over an internet connection if you have one
  • or, run wl2kax25 to send over your configured ax25 stack

The setup I got working is:

  • Raspberry Pi, with alpine (regular email client), direwolf (packet soundcard modem) and ax25 (to link paclink to direwolf)
  • Rigblaster Advantage USB soundcard, connected to an Icom 880

To send over vhf to my nearest Winlink gateway, I used:

  • wl2kax25 -a 1 -c KG6SJT-10 via KBERR

Where

-a 1 is port 1 defined in my /etc/ax25/axports

-c is the call of the Winlink gateway I’m connecting to, and I’m connecting via a packet digipeater, KBERR.