Become an APRS Weather Alert Station

Most of us are familiar with the SAME codes used by NOAA Weather Radio All Hazards transmissions.  They allow the radio to be unmuted for Warning/Watch/Advisory (W/W/A) announcements for a county or zone.  I thought it would be a good idea to add W/W/A functionality to my existing APRS station.  I have been transmitting and iGating local weather readings via APRS for a number of years as part of the Civilian Weather Observer Program (CWOP).

My APRS station uses aprx software.  aprx runs under Linux, so I run mine on a Raspberry Pi Model B with Raspbian.  aprx supports the ability to run an external program as a beacon.  I wrote my program (noaacap.py) to be run by the aprx beacon exec function.

noaacap uses the NOAA CAP (Common Alerting) protocol and the Atom feeds published by the National Weather Service.  Installation is quick and simple if you have a running aprx system.

This is what my alerts look like after being iGated to APRS-IS.  They also go out over RF to the region.  I can even map the alerts on an APRS GUI such as Xastir.

Weather alert map @ K2DLS-13 during Hurricane Jose

If you’d like to become an APRS weather alert station for your county, consider running aprx and noaacap. You’ll need a 2 meter transceiver, a TNC (hardware or virtual), and an antenna to tranmsit the data feed via RF.  Help keep fixed and mobile stations, especially those using radios with APRS display screens, well informed and situationally aware.  You don’t have to run a high profile digipeater.  If your APRS signal is receivable by a local digipeater, you could even use an HT, a sound card interface, and an RPi to assemble a low cost station and provide this valuable local service via amateur radio.

More information about noaacap can be found on my github page.

aprx and weather reporting

I’ve been sending weather reports via APRS-IS and RF for some years and have recently re-architected the way it works.  My APRS station uses aprx software running on a Raspberry Pi Model B.

My weather station is a Davis Vantage Vue with WeatherLinkIP module. The module allows the weather station to plug directly into my ethernet network. I formerly used WeatherLinkIP to feed the data to CWOP which would in turn show up on APRS-IS.  I would then gateway my reports back to RF using an aprx filter.  This seemed convoluted to me, so I wanted to improve things.

I now use a program called Weather Display, a very capable weather program, which has the capability to generate an APRS WXNOW.TXT file.  Weather Display can directly poll the Davis station via IP.  Through the steps documented below, I now send my weather reports via RF and APRS-IS in the same step.

Every 10 minutes, via crond, I perform some preprocessing on the WXNOW.TXT file to embed the weather report in the APRS “Complete Weather Report Format — with Lat/Long position and Timestamp” and then secure copy the file over to my Raspberry Pi APRS system:

#!/bin/bash
#
if [ ! -f ~/tmp/WXNOW.TXT ]; then
   exit 1
fi
# Change to the Lat/Long of your weather station
LATLONG="4023.75N/07412.53W"
line=0
while read FILE; do
   if [ $line = 0 ]; then
      # Change America/New_York to your timezone
      TIME=`TZ=UTC date --date="TZ=\"America/New_York\" $FILE" +%d%H%M`
      line=$((line+1))
   fi
WX=$FILE
done < ~/tmp/WXNOW.TXT # echo /$TIME\z$LATLONG\_$WX > ~/tmp/wxnow.tmp
# 
echo `cat ~/tmp/wxnow.tmp | tr -d '\r'`XDsIP > ~/tmp/wxnow.txt
# You must setup ssh key based authentication for this to work
# Another method could be a file copy via NFS or CIFS
scp ~/tmp/wxnow.txt pi@aprs:/dev/shm/wxnow.txt
# 
rm ~/tmp/wxnow.txt ~/tmp/wxnow.tmp

On the APRS host, I defined the following beacon section in /etc/aprx.conf:

beaconmode both
cycle-size 10m

beacon via WIDE2-1 \
srccall N0CALL-13 \
exec /usr/local/bin/aprx-wxnow.sh

Finally, the beacon exec script, is installed in /usr/local/bin/aprx-wxow.sh:

#!/bin/bash
#
TIME=$(printf `date -u "+%d%H%M"`)
if [ -f /dev/shm/wxnow.txt ]; then
   if [ -f /dev/shm/wxold.txt ]; then
      FULLWXOLD=`cat /dev/shm/wxold.txt`
   else
      FULLWXOLD=""
   fi
   FULLWXNOW=`cat /dev/shm/wxnow.txt`
   if [ "$FULLWXOLD" == "$FULLWXNOW" ]; then
      # Convert date/times to minutes for date arithmetic
      CURDAY=`echo $TIME | cut -b 1-2`
      OLDDAY=`echo $FULLWXOLD | cut -b 2-3`
      CURHR=`echo $TIME | cut -b 3-4`
      OLDHR=`echo $FULLWXOLD | cut -b 4-5`
      CURMIN=`echo $TIME | cut -b 5-6`
      OLDMIN=`echo $FULLWXOLD | cut -b 6-7`
      CURTIME=$((10#$CURDAY * 1440 + 10#$CURHR * 60 + 10#$CURMIN))
      OLDTIME=$((10#$OLDDAY * 1440 + 10#$OLDHR * 60 + 10#$OLDMIN))
      # If report older than 20 minutes then not updating
      if (( $(($CURTIME-$OLDTIME)) > 20 )) ; then
         echo -n \>$TIME\z
         echo " WX rpt not updating"
         exit 0
      fi
      # Unchanged report but <= 20 min old then don't transmit
      echo
      exit 0
   else
      OLDRPT=`echo $FULLWXOLD | cut -b 9-`
      NEWRPT=`echo $FULLWXNOW | cut -b 9-`
      #if new and old report are same then don't transmit
      if [ "$OLDRPT" == "$NEWRPT" ]; then
         echo
         exit 0
      fi
      # Transmit report and copy wxnow.txt to wxold.txt
      echo $FULLWXNOW cp /dev/shm/wxnow.txt /dev/shm/wxold.txt
   fi
else
   echo -n \>$TIME\z
   echo " WX rpt not found"
fi

While debugging, I noticed that the wxnow.txt file would sometimes disapper from /dev/shm.  This turned out to be systemd cleaning up interprocess communication whenever the pi user logged out.  I fixed this by adding the following line to /etc/systemd/logind.conf:

RemoveIPC=no

Following this change, you must restart systemd-logind.service:

sudo systemctl restart systemd-logind.service

If you implement this on your aprx system, please leave a comment.