Send APRS data/telemetry via Xastir command line

In my previous post I wrote about sending objects and telemetry via command line to APRS-IS server.

You can also do that with Xastir, but as a bonus point, you can do it all via RF if your Xastir setup is already paired to the radio and configured to transmit. You can use the scripts from my previous blog post, you only need to change some commands.

Xastir GUI is lacking options to send multiple different beacons or telemetry data. There is a binary called xastir_udp_client that comes with normal Xastir setup which takes care of that, but you need to run it from a command line and do some custom scripting. To use this feature, you need to enable server ports. Open xastir, go to interface menu and click enable server ports.

The basic commands to create an object with a house icon are:

Send via RF:

xastir_udp_client XastirIP port user passcode -to_rf 'senduser>APN100,WIDEPATH*:=latitude/longtitude-Comment'
xastir_udp_client 192.168.0.140 2023 S55MA-10 22558 -to_rf 'S55MA-10>APN100,WIDE2-1*:=4539.94N/01417.67E-QTH'

Send via Internet only (remove -to_rf):

xastir_udp_client XastirIP port user passcode 'senduser>APN100,TCPIP*:=latitude/longtitude-Comment'
xastir_udp_client 192.168.0.140 2023 S55MA-10 22558 'S55MA-10>APN100,TCPIP*:=4539.94N/01417.67E-QTH'

Why did I write “senduser” in string? Because you can place remote objects on the map that’s not your own call sign – sticking to the protocol rules, you need to change the code to show the correct path if you want to place objects with not your own sign. The only drawback with Xastir in this example is, it overrides your permanent timestamp (111111z). More info about sending objects with not your sign is in my previous post. Why is it so “cool” to collect and send data from another stations to RF? Let’s say you want to transmit critical data to offline users like repeater offset or echolink node number. You can also transmit weather data from other non RF stations to RF. So for example if I’m walking in the forest with my handheld APRS capable station I can receive weather or repeater data directly on my handheld without having the internet.

Example:

I’m collecting data from this weather station: https://www.hobolink.com/p/d0a7b4f0dbc44b973b0a5cce75a0521d and sending it to RF, including telemetry.

https://aprs.fi/weather/S51Y

Another example is sending repeater and echolink data to RF:

You see that purple lines? That means the object was put on the map via my station (S55MA-10).

You can also see the path at the bottom of a white rectangle “[APN101 via WIDE2-1,qAR,S55MA-10]”

Note that this is actually faking an object, it looks like the transmitter is at the object and it’s

being igated by my station, but it’s actually my station doing the transmissions. This is a good example  how to not

stick to the protocol rules 😉 I was unable to do it with xastir_udp_client binary, it rewrites it’s path if you want to send another

object. There is also a “bug” or a feature, I’m not sure yet, that xastir_udp_client inserts additional } in the string. I don’t know

why is that, but it’s unwanted.

If you want to show that remote object is put on the map by your station, you need to change the path as I mentioned above,

stick to the protocol, but I don’t think that’s possible with xastir_udp_client. I neglected this and I’m going to update my scripts

if I find the correct solution.

Example script I’m using to send Echolink data to RF:

#!/bin/bash

#Transmit objects via Xastir to RF.

#Define login info
user=S55MA-10
password=23458

#Define object user info
usersend=S55UPO-10

#Define xastir server
server=192.168.0.140
port=2023

#Define station location (Echolink Postojna, Pecna Reber)
lat=4546.72N
lon=01413.80E

#Define data
comment="Echolink Postojna 438.825Mhz -7.6M T123 Node:609569"
data="$usersend>APN101,WIDE2-1:=${lat}E${lon}0${comment}"

#Send object to RF
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$data"

#Debugging
#printf "$data\n"

Example of my hobolink weather collector script. Hobolink to APRS. It’s similar to the script in my previous post so I won’t go into details.

#!/bin/bash

#Read data from HOBOlink station and send it to APRS network via Xastir. Server ports option has to be enabled on Xastir.

#Create a temporary RAM disk (we don't want to write on a SD card too often).
#You need to run this script as sudo (root) or create a temporary ramdisk at boot as root
#and run this script as a normal user.
if [ ! -d "/mnt/ramdisk/" ]; then
mkdir -p /mnt/ramdisk; mount -t tmpfs tmpfs /mnt/ramdisk -o size=10m
fi

#Check if file exist
if [ ! -f "/mnt/ramdisk/sequence_numberjavornik.txt" ]; then
touch /mnt/ramdisk/sequence_numberjavornik.txt
fi

#Read sequence number
read num < /mnt/ramdisk/sequence_numberjavornik.txt
num=$((num + 1))
if (( num == 1000 )); then
num=0
fi

#Error log file
error=/var/log/wxdata.log

#Define login info
user=S55MA-10
password=passcode

#Insert the same as user. Insert other user sign if you want to put another station not owned by you on the map. Be aware that telemetry
#requires 9 char long callsign so you need to add whitespaces after the callsign and telemetry, for example:
#t2="$usersend>APN002,WIDE2-1::"$usersend" :PARM.Solar Radiation,Battery" #5 whitespaces between "$usersend" and :PARM because
#S51Y is only 4 char long.
usersend=S51Y

#Define xastir server
server=192.168.0.140
port=2023

#Define station location (Veliki Javornik, Postojna)
lat=4545.48N
lon=01417.72E_ #_ is a symbol for WX station

#Download weather data
file=/mnt/ramdisk/wxdata.txt
file1=/mnt/ramdisk/wxdata1.txt
curl -s https://www.hobolink.com/p/d0a7b4f0dbc44b973b0a5cce75a0521d | grep nobr | awk -F\> '{print $6}' | sed 's/<\/nobr//g' > "$file"
curl -s https://www.hobolink.com/p/d0a7b4f0dbc44b973b0a5cce75a0521d | grep "Wind Direction" -A 1 | grep "latest-conditions-info-reading" | awk -F\> '{print $5}' | awk '{print $2}' | grep -o '[0-9]\+' > "$file1"

if [ -s "$file" ] #If downloaded file is not empty, continue, else quit
then

#Date in UTC
zuludate="$(date -u +%d%H%M)"

#APRS needs temperature in F, data is fetched in degress C so we need to convert it.
tempC="$(sed -n -e 1p "$file")"
tempF="$(echo "((9/5) * $tempC) + 32" | bc -l | awk -F. '{print $1}')"

#Relative humidity
rh="$(sed -n -e 2p "$file" | awk -F. '{print $1}')"

#APRS need windspeed in mph, data is fetched in meters per second so we need to convert it.
windspeedms="$(sed -n -e 4p "$file")"
windspeedmph="$(echo "(($windspeedms * 3.6) / 1.609344)" | bc -l | awk -F. '{print $1}')"
gustsms="$(sed -n -e 5p "$file")"
gustsmph="$(echo "(($gustsms * 3.6) / 1.609344)" | bc -l | awk -F. '{print $1}')"

rain1h="$(sed -n -e 7p "$file" | awk -F. '{print $1}')"
winddirection="$(cat "$file1")"
solarradiation="$(sed -n -e 6p "$file")" #For telemetry only
batteryvoltage="$(sed -n -e 8p "$file" | tr -d '.' | head -c 3)" #For telemetry only

#Station comment
aprscomment="Veliki Javornik 1268m asl"

#Xastir weather variable with padding zeros for correct APRS format
printf -v xastirwx "%03d/%03dg%03dt%03dr%03dh%02d%s" "$winddirection" "$windspeedmph" "$gustsmph" "$tempF" "$rain1h" "$rh" "$aprscomment"

#Xastir user and WIDE path data
xastirpath="$usersend>APN100,WIDE2-1:=$lat/$lon"

#Telemetry
printf -v t1 "%s>APN002,WIDE2-1:T#%03d,%03d,%03d,000,000,000,00000000" "$usersend" "$num" "$solarradiation" "$batteryvoltage"
t2="$usersend>APN002,WIDE2-1::$usersend :PARM.Solar Radiation,Battery"
t3="$usersend>APN002,WIDE2-1::$usersend :UNIT.W/m2,Volts"

#Add coefficient in EQNS field to convert real data.
t4="$usersend>APN002,WIDE2-1::$usersend :EQNS.0,1,0,0,0.01,0,0,0,0,0,0.0,0,0,0,0"
t5="$usersend>APN002,WIDE2-1::$usersend :BITS.00000000,Weather station Veliki Javornik Postojna"

#Send data to Xastir
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$xastirpath$xastirwx"

#Send telemetry data to Xastir
#Send PARAMS, UNITS, EQNS and BITS every 2 hours.
#Check if file exist
if [ ! -f "/mnt/ramdisk/datejavornik.txt" ]; then
echo 0 > /mnt/ramdisk/datejavornik.txt
fi

#calculate time difference
read olddate < /mnt/ramdisk/datejavornik.txt
date="$(date +%s)"
diff="$(echo "$date - $olddate" | bc)"

if [ "$diff" -gt 7200 ]; then
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$t1"
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$t2"
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$t3"
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$t4"
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$t5"
echo "$date" > /mnt/ramdisk/datejavornik.txt
else
/usr/bin/xastir_udp_client $server $port $user $password -to_rf "$t1"
fi

#Delete old data
rm -f /mnt/ramdisk/wxdata.txt /mnt/ramdisk/wxdata1.txt

#Write sequence number
echo "$num" > /mnt/ramdisk/sequence_numberjavornik.txt

else
echo ["$(date -u)"] Error downloading data >> "$error"
fi

Link to the Hobolink to APRS script: https://pastebin.com/v6cQkm54

3 comments

  1. The “}” character is not a bug in Xastir, it’s intentional.

    Every packet injected into xastir via xastir_udp_client is treated as a third-party packet, which means that Xastir places its own packet header first (indicating the actual transmitting station and software), followed by “}”, followed by the complete packet being injected (the station, object, item, or message packet intended). This identifies to all that Xastir itself is not the source of the packet, only the transmission medium, and the true source of the packet is contained in the information following the “}”

    This is exactly what the APRS protocol says should be done for third-party packets (see chapter 17 of the APRS protocol documentation, http://www.aprs.org/doc/APRS101.PDF)

    If you create a fully-formed APRS packet (complete with from call, to call, and (possibly null) path), all APRS clients should recognize the format and do the right thing with it.

    There was some attempt years ago to make Xastir treat injected data as its own if the callsigns match and send them as a regular packet instead of third-party, but apparently the person who coded that up never got the code to work properly and then just commented it out. So Xastir *always* treats *all* packets injected by xastir_udp_client as third party packets and always inserts the third party header.

Leave a Reply

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