Install npm, Puppeteer and dependencies:

apt update -y && apt upgrade -y
apt install -y npm
apt install -y libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 libxi-dev libxtst-dev libnss3 libcups2 libxss1 libxrandr2 libasound2 libatk1.0-0 libatk-bridge2.0-0 libpangocairo-1.0-0 libgtk-3-0 libgbm1
npm install -g n
n lts
hash -r
npm install puppeteer

Install Chrome without snap:

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
apt install ./google-chrome-stable_current_amd64.deb

Make a test file test.js:

const puppeteer = require('puppeteer');
const fs = require('fs');

async function run () {
  const browser = await puppeteer.launch({
    executablePath: '/usr/bin/google-chrome-stable',
    args: ['--no-sandbox'],
    defaultViewport: {width: 1920, height: 1080}
  });
  const page = await browser.newPage();
  await page.goto('https://www.google.com');
  await sleep(3000);

  await page.screenshot({path: 'screenshot.png'});
  const html = await page.content();
  fs.writeFileSync('source.htm', html);

  browser.close();
}
run();

function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
} 

Test it:

node test.js

1. Update system and optionally disable X Desktop, we don’t need GUI

apt-get update
apt-get upgrade
raspi-config

Select menu: 3, B1, B1

2. Install dependencies

apt-get install subversion libsigc++-2.0-dev g++ make libsigc++-1.2-dev libgsm1-dev screen \
libpopt-dev tcl8.5-dev libgcrypt-dev libspeex-dev libasound2-dev alsa-utils install qt-sdk git groff -y

3. Add a new user

adduser svxlink

4. Download svxlink source

cd /usr/src; wget https://github.com/sm0svx/svxlink/archive/15.11.tar.gz; tar xvf 15.11.tar.gz; cd svxlink-15.11/src; mkdir build; cd build

5. Compile and install svxlink

cmake -DCMAKE_INSTALL_PREFIX=/usr -DSYSCONF_INSTALL_DIR=/etc \
        -DLOCAL_STATE_DIR=/var ..
make
make doc
make install
ldconfig

6. Install sounds

cd /usr/share/svxlink/sounds; wget https://github.com/sm0svx/svxlink-sounds-en_US-heather/releases/download/14.08/svxlink-sounds-en_US-heather-16k-13.12.tar.bz2
tar xvf svxlink-sounds-en_US-heather-16k-13.12.tar.bz2
mv en_US-heather-16k en_US; rm -rf svxlink-sounds-en_US-heather-16k-13.12.tar.bz2

7. Configure sound levels

alsamixer

Press F6 and select usb soundcard.
Press F5 to show all.
Increase gain on CAPTURE, around 80 is fine, experiment otherwise.
Exit alsamixer and save the settings with:

alsactl store

8. Tweak configuration files in /etc/svxlink/svxlink.conf and /etc/svxlink/svxlink.d/ModuleEchoLink.conf

svxlink.conf: I will show you only modified lines

Uncomment LOCATION_INFO=locationInfo to show your Echolink on aprs.fi map.
MODULES=ModuleEcholink
CALLSIGN=Yoursign-L
SHORT_IDENT_INTERVAL=0
LONG_IDENT_INTERVAL=0

Under [Rx1]

AUDIO_DEV=alsa:plughw:1 #Hardware ID of the soundcard, usually 1 on rpi with usb soundcard
SQL_START_DELAY=100 #Prevent TX, RX loop
VOX_THRESH=500 #Increase if your VOX gets falsly opened

Under [Tx1]:

AUDIO_DEV=alsa:plughw:1
PTT_TYPE=SerialPin
PTT_PORT=/dev/ttyUSB0 #Depends what you have for PTT triggering, I do it with RS232 to USB converter

Under [LocationInfo]
#This is mostly self explanatory

APRS_SERVER_LIST=poland.aprs2.net:14580
STATUS_SERVER_LIST=aprs.echolink.org:5199
#Go to maps.google.com, select your location, right click, what's here
#and you'll get coordinates, for example: 45.660325, 14.291537 Go to https://rechneronline.de/winkel/degrees-minutes-seconds.php
#and convert from decimal degrees provided from maps.google.com to degrees, arc minutes, arc seconds.
#Enter converted
#coordinates.

LON_POSITION=14.17.29E
LAT_POSITION=45.39.37N
CALLSIGN=EL-yourcallsign
FREQUENCY=145.275
TX_POWER=5
ANTENNA_GAIN=0
ANTENNA_HEIGHT=5m
ANTENNA_DIR=-1
PATH=WIDE1-1
BEACON_INTERVAL=10
TONE=123
COMMENT=SvxLink by SM0SVX (svxlink.sourceforge.net)

ModuleEcholink.conf:

ALLOW_IP=192.168.0.0/24 #Depends on your home network setup,
#it could be also ALLOW_IP=192.168.1.0/24
SERVERS=europe.echolink.org
CALLSIGN=yoursign-L
PASSWORD=your echolink password
SYSOPNAME=yourname
LOCATION=[Svx] comment about your echolink
LINK_IDLE_TIMEOUT=0
AUTOCON_ECHOLINK_ID=ID of the remote repeater for example AUTOCON_ECHOLINK_ID=609569
AUTOCON_TIME=1200
DESCRIPTION=edit text to fit your needs
reboot

9. Run svxlink

svxlink

Try to transmit, usb soundcards on rpi are tricky. You will probably get a warning:
Rx1: Distorsion detected! Please lower the input volume!
Don’t worry about it.
Exit and run svxlink as daemon

svxlink --daemon

10. Start svxlink at boot
You need to wait some time after boot for Pi to initialize devices.
It will not work when you start svxlink immediately after the boot,
the process will run but there will be no access to PTT. Open
/etc/rc.local and add this two lines at the end of the file, before exit 0

sleep 120
/bin/bash -c '/usr/bin/svxlink --pidfile=/var/run/svxlink.pid --daemon'

This will start svxlink 2 minutes after boot.

#!/bin/sh

# Get APRS weather data from aprs.fi

wxstation="S55MA-10"

# Basic weather data
temp="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Temperature | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o)"
humidity="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Humidity | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o)"
wind="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Wind | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o | sed -n -e 2p)"
rain="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Rain | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o | sed -n -e 1p)"

# Telemetry
radioactivity="$(wget -q https://aprs.fi/telemetry/a/${wxstation} -O - | grep Radioactivity | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o | sed -n -e 5p)"

printf "%s\n" "Temperature: ${temp}°C" "Humidity: ${humidity}%" "Wind: ${wind} m/s" "Rain: ${rain} mm/h" "Radioactivity: ${radioactivity} uSv/h"

Enable server ports on Xastir. We need to use the command line binary xastir_udp_client which is part of Xastir. To send the data over RF, you need to have Xastir configured with your transmitter already.

More info about the mail APRS service: http://www.aprs-is.net/email.aspx

The basic string is:

xastir_udp_client XastirIP port callsing passcode -to_rf 'callsign>APRS::EMAIL    :EmailOfReceiver@something.com message'

Real example:

xastir_udp_client 192.168.0.140 2023 S55MA-10 22222 -to_rf 'S55MA-10>APRS::EMAIL    :s55ma@radioamater.si hello'

Note: You may only send one line messages of 64 total characters maximum for the message even though the documentation is saying 67. You have to put 4 white spaces between EMAIL and EmailOfReceiver, so the total lenght of EMAIL+white spaces is 9 characters.

This post is about Xastir, but on the side note, most APRS capable handhelds stations are not able of sending email messages through APRS. One portable station that’s able to do it is Kenwood TH-D72. I found this post about it. Too bad other portables are not able to do that where this feature is the most usefull, I mean, it’s not like I’m going to need aprs to email service from my home station, I’d likely need it outdoors for emergency situations or to send an email when I’m abroad and without cellular data service.

Quick script for sending messages:

#!/bin/bash

#APRS to Email script using Xastir
#Define variables
#Xastir server and port
server=192.168.0.140
port=2023

#Authentication info
user=S55MA
passcode=22222

echo "Enter sender (yours or some others callsign)"
read sender
sendercapital="$(echo $sender | awk '{print toupper($0)}')"

echo "Enter destination email:"
read email

echo "Enter your message (max 64 characters):"
read message

#Count message characters
msglenght="$(echo $message | wc -c)"

#Restart script if message exceeds 64 characters.
if [ "$msglenght" -gt 64 ]; then
echo "Your message exceeded 64 characters, try again!"
exec bash "$0"
else
xastir_udp_client $server $port $user $passcode -to_rf "$sendercapital>APRS::EMAIL    :$email $message" >/dev/null 2>&1
echo "Message has been sent."
fi

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

This is to internet only, not to RF. You need TNC software and a radio station to send it via RF.

We need ncat which is a part of nmap and bc.

sudo apt-get install nmap bc

First, some usefull tools:
APRS coordinate converter: http://digined.pe1mew.nl/?How_to:Convert_coordinates
APRS passcode generator: http://apps.magicbug.co.uk/passcode/

There are more APRS IS servers available to connect to, I decided to use poland.aprs2.net, the generic one is rotate.aprs.net.
Default port is 14580.

The protocol goes like this (more info http://www.aprs-is.net/Connecting.aspx):
– Authenticate with APRS-IS server
– Send data

So the data you are sending is:
– user yourHAMSIGN pass passcode
– objectdata

Bash one line command to send data:

printf "%s\n" "user yourHAMSIGN pass passcode" "yourHAMSIGN>APN100,TCPIP*:=latitude/longtitude-comment" | ncat poland.aprs2.net 14580

Example:

printf "%s\n" "user S55MA-13 pass 23558" "S55MA-13>APN100,TCPIP*:=4246.29N/01412.79E_247-QTH" | ncat poland.aprs2.net 14580

This should place S55MA-13 on a map with a house icon.
Look into aprs.fi raw data for your ham sign (https://aprs.fi/?c=raw&call=yourHAMSIGN) to find any formatting errors. It should look like this:

2017-07-27 16:18:32 CEST: S55MA-13>APN100,TCPIP*,qAC,T2POLAND:=4246.29N/01412.79E_247-QTH

Important: With this commands you can place (fake) or “steal” an objects that are not your own stations by placing another station sign in the second yourHAMSIGN field. This will work, but it will look like the object is coming via another station, igated by your station. That’s ok, the object will be placed correctly on the map, but for the sake of following correct protocol procedures, you need to change a string a little bit so the other station object will show correct path of where it’s coming from.

When placing another object (not your own) on the map, you need to add the timestamp to the string. If the object is permanent, timestamp should be “111111z” (http://www.aprs.org/info/object-perm.txt)

Example:

printf "%s\n" "user yourHAMSIGN pass passcode" "yourHAMSIGN>APN100,TCPIP*:;ANOTHERSTATION_CALLSIGN *111111zlatitude/longtitude-comment" | ncat poland.aprs2.net 14580
printf "%s\n" "user S55MA-10 pass 22358" "S55MA-10>APN100,WIDE2-1*:;S55MA-14 *111111z4139.94N/01217.67E-test" | ncat --send-only poland.aprs2.net 14580

Note: ANOTHERSTATION_CALLSIGN is by protocol defined as 9 characters long and you need to add whitespaces between ANOTHERSTATION_CALLSIGN and *111111z
Example: S51Y has four characters only so you need to add 5 whitespaces between ANOTHERSTATION_CALLSIGN and *111111z
The string would look like:

printf "%s\n" "user S55MA-10 pass 22358" "S55MA-10>APN100,WIDE2-1*:;S51Y     *111111z4139.94N/01217.67E-test" | ncat --send-only poland.aprs2.net 14580

If you don’t want to use one line command, you can create a simple script (for placing your own station):

#!/bin/bash

#Define login info
user=yourHAMSIGN
password=passcode

#Define object user info
senduser=yourHAMSIGN

#Define APRS-IS server
server=poland.aprs2.net
port=14580

#Define station location
lat=4146.72N
lon=01213.80E

#Define data
comment="QTH"
data="$senduser>APN100,TCPIP*:=${lat}/${lon}-${comment}"

#Send data to the server
printf "%s\n" "user $user pass $password" "${senduser}>APN100,TCPIP*:=${lat}/${lon}-${comment}" | ncat poland.aprs2.net 14580

NOTE: Don’t send data to often. For objects it’s sufficient to send it every few hours. Don’t spam the network.

You can send telemetry the same way but it’s a little bit trickier because APRS protocol has coeficients for displaying the correct values.
For example let’s say we’ll read a raspberryPI CPU temperature and send it to APRS-IS network.

#!/bin/bash
#Define login info
user=yourHAMSIGN
password=passcode

#Define object user info
senduser=yourHAMSIGN

#Define APRS-IS server
server=poland.aprs2.net
port=14580

#Define station location
lat=4146.72N
lon=01213.80E

#Define data
comment="QTH"
data="$senduser>APN100,TCPIP*:=${lat}/${lon}-${comment}"

#Authentication variable
aprsauth="user $user pass $password"

#Read raspberry-pi CPU temperature
tempraw=/opt/vc/bin/vcgencmd measure_temp #Read pi temperature

#Filter result to numbers only 
tempfloat="$(echo "$tempraw" | awk -F= '{print $2}' | awk -F\' '{print $1}')"

#Aprs telemetry protocol accepts 3 whole (int) 
#numbers only so we need
#to convert the result (tempfloat) into 3 whole 
#numbers. So if tempraw=40.3, it will
#convert it to 403. If tempraw=8.5, it will convert 
#it to 85 and we'll add the leading zero
#to create 3 number format 085 later bellow.
temp="$(echo "$tempfloat * 10" | bc | awk -F. '{print $1}')"

#Project comment
projectcomment=Rpi temperature

#Generate telemetry strings
#Read data and put it into variable
#%s means string
#%03d means prepend up to 3 zeroes, so if the value is 8, 
#you'll get 008, if the value is 80, you'll get 080 etc.
#This needs to be done or APRS will deny the packets as invalid. 
#The other things is, everytime you send the telemetry,
#a sequence number has to change, it's defined as T# in a APRS protocol. 
#We will automate this next.

#Check if file exist
if [ ! -f "/tmp/sequence_number.txt" ]; then
 touch /tmp/sequence_number.txt
fi

#Read sequence number. Everytime the scripts runs, the number will 
#rise by 1 until it comes
#to 1000 and then returns back to 0. Everytime the script
#will run, a sequence number will change.
read num < /tmp/sequence_number.txt
num=$((num + 1))
if (( num == 1000 )); then
 num=0
fi 

#Finally, we can start assembling the data. 
#$senduser goes to %s, $num goes to first %03d and $temp goes to 
#the last %03d in the string. 
printf -v t1 "%s>APN001,TCPIP*:T#%03d,%03d,000,000,000,000,00000000" "$senduser" "$num" "$temp"

#Define telemetry parameters
t2="$user>APN001,TCPIP*::$senduser :PARM.CPU Temp"

#Define telemetry units
t3="$user>APN001,TCPIP*::$senduser :UNIT.Deg.C"

#Add telemetry coefficient so the APRS protocol can convert your raw values
#into real value.
#We get the value in 3 whole numbers and we need to define coefficient so 
#the APRS protocol
#will know how to display the value. We add 0.1 to the second field, means
#if the value is 452, the temperature will be displayed as 45.2
t4="$user>APN001,TCPIP*::$senduser :EQNS.0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0"

#Send bits and project comment
t5="$user>APN001,TCPIP*::$senduser :BITS.00000000,$projectcomment"

#Another tricky part is, $senduser total lenght has to be 9 characters. 
#For example
#If my $senduser=S55MA-10 means it's only 8 characters long and we need 
#to add 1 space to it. S55MA-10 :PARM
#If my $senduser=S55MA means it's only 5 characters long and we need to 
#add 4 spaces to it S55MA    :PARM
#The same goes for UNIT, EQNS and BITS

#Send data to the server
#For telemetry to work we need to have an object before, from previous script.
#We'll only send an object and telemetry non value data every hour so we don't 
#spam the network.
#We need to compare dates to see if 1 hour is past.

#Check if file exist
if [ ! -f "/tmp/date.txt" ]; then
   echo 0 > /tmp/date.txt
fi

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

#If 3600 is past, execute the first command, else other
if [ "$diff" -gt 3600 ]; then
   printf "%s\n" "$aprsauth" "$data" | ncat --send-only $server $port #this is your QTH object from the first script
   printf "%s\n" "$aprsauth" "$t1" "$t2" "$t3" "$t4" "$t5" | ncat --send-only $server $port 
   echo "$date" > /tmp/date.txt
else
   printf "%s\n" "$aprsauth" "$t1" | ncat --send-only $server $port
fi
#Write the last sequence number.
echo "$num" > /tmp/sequence_number.txt

Telemetry should form on aprs.fi, for example: https://aprs.fi/telemetry/a/S55MA-10
Note, formatting in script might be broken due html formatting, here is a raw script: https://pastebin.com/24CaMXLT

I’ve bought an affordable geiger counter board that fits on a Raspberry pi zero (https://www.tindie.com/products/granzscientific/raspberry-pi-zero-iot-geiger-counter/).  I’ve modified original software and added some scripts to send radiation readings to the APRS network. I’ve also added a Munin plugin. Go to the github project site for instructions: https://github.com/s55ma/granzscientific-geiger-counter-APRS

Pi-Hole is a DNS based ad blocker. You can install it on a Debian based Linux distributions. To use it together with a PfSense firewall you need to change a few firewall settings:

  • Login to your PfSense and go to System -> General Setup:

In the first DNS Server field insert the IP of your Pi-Hole computer and save changes

  • Go to Services -> DNS Resolver:

Tick Enable DNS resolver

Tick Enable DNSSEC Support

Tick Enable Forwarding Mode (this will tell the PfSense to use a DNS server that we configured in a general settings in the previous step)

Save and that’s it.

This post will show you how to generate weather data from LA Crosse WS2300 series weather stations for submission to the APRS network.

APRS software I’m using is Xastir, but you can use this setup to push the weather data to other APRS applications also. Digipeater mode is already set up in Xastir. This post will not cover digipeating WX data.

1. Install packages

apt-get update

apt-get install  bc ncat unzip gcc build-essential

2. Download open2300 and compile fetch2300

Fetch2300 is part of open2300, it’s used to connect to the weather station and return the data. Credit goes to Kenneth Lavrsen (http://www.lavrsen.dk/foswiki/bin/view/Open2300)

wget -O "open2300-1-10.zip" https://sourceforge.net/projects/open2300/files/open2300/1.10/open2300-1.10.zip/download"

unzip open2300-1-10.zip

cd open2300-1.10

make fetch2300

cp fetch2300 /usr/local/bin/fetch2300



3. Edit  and rename open2300 config file named open2300-dist.conf or copy mine to /etc/open2300/open2300.conf

mkdir -p /etc/open2300

nano /etc/open2300/open2300.conf
SERIAL_DEVICE /dev/ttyUSB1 #/dev/ttyS0, /dev/ttyS1, COM1, COM2 etc
TIMEZONE 1 # Hours Relative to UTC. East is positive, west is negative
WIND_SPEED km/h # select MPH (miles/hour), m/s, or km/h
TEMPERATURE F # Select C or F
RAIN IN # Select mm or IN
PRESSURE hPa # Select hPa, mb or INHG

Note: make sure you select the correct SERIAL_DEVICE in the config. The station in my setup

is connected via USB to RS232 converter so the device is ttyUSB0. Also, don’t change the units, bash script will automatically convert them to be compatible with APRS network.

4. Copy bash script to desired location

mkdir -p /root/ws2300/

nano wxdata_v1.6.sh
#!/bin/bash

#This script reads weather data via fetch program which is part of Open2300 suite written by Kenneth Lavrsen (http://www.
#lavrsen.dk/foswiki/bin/view/Open2300/WebHome).
#It outputs the right data needed to feed Xastir for APRS weather reports. The scripts utilizes Ncat utility as server to
#serve the fetched output to Xastir.
#Fetched Data is pushed to Ncat server and then to Xastir. (Fetched data -> Ncat server -> Xastir)
#Ncat is part of Nmap, get it by installing Nmap.
#This script should work for LaCrosse weather stations, WS23xx series. Testing was done with WS2307.
#Written by S55MA and S56IUL, May 2016

#DEFINE VARIABLES
host="127.0.0.1"
port="1234"

#Start the Ncat server
chkncat=$(netstat -ant | grep $host:$port | grep -c LISTEN)
if [ "$chkncat" -ge "1" ]
then
echo "ncat already running, nothing to do"
else
nohup ncat -k -l --broker $host $port &>/dev/null &
fi

#Start while loop
while true; do

echo "start `date`"

datetime=$(date '+%Y%m%d%H%M%S')
ws2300config="/etc/open2300/open2300.conf"
/usr/local/bin/fetch2300 $ws2300config > /tmp/wxdata-"$datetime".tmp
fetch_path="/tmp/wxdata-$datetime.tmp"
chkfile=$(ls -la $fetch_path | awk -F ' ' '{ print $5 }')

if [ "$chkfile" -le "43" ]
then
echo "No Data"
sleep 30
else
tempF=$(cat "$fetch_path" | grep To | grep -v 'min\|max\|DRtot\|TRtot' | awk '{print $2}')
temp1=$(echo "$tempF" | awk '{ printf ("%d\n",$1 + 0.5)}')
if [ "$temp1" -ge "99" ] || [ "$temp1" -le "-99" ]
then
temp="$temp1"
else
if [ "$temp1" -le "-1" ]
then
if [ "$temp1" -ge "-9" ]
then
temp2=$(echo "$temp1" | sed 's/[-]//g')
temp=$(echo -0"$temp2")
else
temp2=$(echo "$temp1" | sed 's/[-]//g')
temp=$(echo -"$temp1")
fi
else
temp=$(echo 0"$temp1")
fi
fi

windspeed2=$(cat "$fetch_path" | grep -m1 WS | grep -v 'min\|max\|DRtot\|TRtot'| awk '{print $2/1.609344}' | awk '{ printf ("%d\n",$1 + 0.5)}')
if [ "$windspeed2" -le "9" ]
then
windspeed=$(echo 00"$windspeed2")
else
if [ "$windspeed2" -le "99" ]
then
windspeed=$(echo 0"$windspeed2")
else
windspeed=$(echo "$windspeed2")
fi
fi

winddirection2=$(cat "$fetch_path" | grep DIR0 | awk '{print $2}' | sed 's/\..*$//')
if [ "$winddirection2" -le "9" ]
then
winddirection=$(echo 00"$winddirection2")
else
if [ "$winddirection2" -le "99" ]
then
winddirection=$(echo 0"$winddirection2")
else
winddirection=$(echo "$winddirection2")
fi
fi

rain1h=$(cat "$fetch_path" | grep R1h | grep -v 'min\|max' | awk '{print $2}' | sed 's/[.]//g')
rain24h=$(cat "$fetch_path" | grep R24h | grep -v 'min\|max' | awk '{print $2}' | sed 's/[.]//g')

airpressureR=$(cat "$fetch_path" | grep RP | grep -v 'min\|max' | awk '{print $2}')
airpressure2=$(echo "scale=1;$airpressureR / 1" | bc | sed 's/[.]//g')
if [ "$airpressure2" -le "9999" ]
then
airpressure=$(echo 0"$airpressure2")
else
airpressure=$(echo "$airpressure2")
fi

relhumidity=$(cat "$fetch_path" | grep RHo | grep -v 'min\|max' | awk '{print $2}' | sed 's/\..*$//')

#Combine variables to forge Xastir string
xastir="c${winddirection}s${windspeed}t${temp}r${rain1h}p${rain24h}b${airpressure}h${relhumidity}xDvs"
printf "%s\n" "$xastir" | ncat --send-only $host $port
echo "$xastir"
sleep 3

rm -f /tmp/wxdata-*.tmp

echo "stop `date`"
echo "-----------------------------------"
fi

done

#EOS



If there are some formatting mistakes, the script is also available on pastebin: http://pastebin.com/29q8epF8

5. Start the script

/root/ws2300/wxdata_v1.6.sh

You should see output similar to that:

start Tue May 3 00:36:47 CEST 2016
c112s013t048b10037h85xDvs

Leave the script running, open another terminal and check if ncat is getting data:

ncat localhost 1234

Wait a few seconds and you should get the result similar to that:

c112s018t048b10037h85xDvs



6. Go to Xastir and add the WX interface

Interface -> Interface Control -> Add -> Networked WX

WX Host: 127.0.0.1

WX Port: 1234

Save and start the interface.

wx_interface

7. Go to Xastir, View -> Own Weather Data

You should see your own weather data from the station

wx_data

8. Start the script at boot and run it in background

Open /etc/rc.local and add

screen -d -m /root/ws2300/wxdata_v1.6.sh

Save and exit

Note: make sure you set your own path of the script location

 

My HW/SW setup:

Dongle: SDR USB Dongle (Realtek RTL2832U R820T chipset, other SDR dongles may also work). Search Ebay for RTL2832U dongles. They should all work.

OS: Windows 7, 64bit

Capture software: SDR# from sdrsharp.com

Decoder: AFSK1200

Note: Don’t install any software drivers that came with the SDR Dongle. Uninstall the drivers, if you already installed them.

1. Setup stereo mix:

Stereo mix is used to forward output sound to the microphone input. We need this, because AFSK1200 decoder will be listening to the microphone input. Open sound options in control panel or just go to start and enter mmsys.cpl. Using USB headset will not work, you need analog speakers. There are some workarounds to use USB headsets but I haven’t tried them yet.

Playback tab: set speakers to the default device.

speakers

Recording tab: if you don’t see the “Stereo mix device”, it’s probably hidden.

  • Right click anywhere in the field where devices are listed and tick “Show disabled devices“, “Show disconnected devices. Stereo mix shold be available now.
  • Right click on it and select “Enable“.

recording2

2. Download  and configure SDR# software:

  • Download http://sdrsharp.com/downloads/sdr-install.zip
  • Extract it and run install.bat
  • Plug in your SDR dongle, go to sdrsharp folder and run zadig.exe. Go to Options and tick “List all devices“. Select “Bulk-In, Interface (Interface 0)” and click “Install Driver”. (On my screenshot, you can see “Reinstall Driver, because I already installed it). Note: You will need to install driver again if you replug the dongle in another USB port.

zadig

  • Run SDRSharp.exe
  • Source -> RTL-SDR (USB)
  • Radio -> NFM, enable Squelch and set it between 50 and 80, you can increase or decrease it depending on your surrounding environment
  • Frequency Manager -> New -> add the frequency you want to monitor, in my case it’s 144.800 Mhz.
  • Click on Play button at the top of SDR# You will see spikes when something is transmitting on the frequency

sdrsharp

3. Decode packets with AFSK 1200 Decoder:

  • Download AFSK 1200 Decoder
  • Select Input and choose Stereo mix
  • Click play button. You are now decoding APRS packets

afsk1200

Don’t forget to disable stereo mix and set the default playback device as you had before when you finish decoding.

I used my RaspberryPI to setup an APRS digipeater. The software I used is called Xastir. The problem is, there are no good default maps to use in Xastir.

This tutorial will guide you how to install OSM maps into Xastir software. Maps are generated on a Windows machine, then transferred to a Linux machine where Xastir is running.

TL;DR version:

1. Download Taho application for Windows.

2. Select area, copy bbox text.

3. Paste bbox text to Taho, click on bbox button, select parameters and click on make maps.

4. Upload generated .inf and .jpg files to your Xastir map folder.

5. Download inf2geo.pl to your linux machine and convert .inf files to .geo files.

6. Start or restart Xastir, select your map and apply.

 

Detailed version:

1. Download Taho application for Windows (Version 4.01 didn’t work on my PC, you should download older versions, if you can’t run the newest version).

2. When you launch the Taho application, it will also open the bbox tool site.

3. On the bbox tool site, center map to your desired location and click button “select area”. Select your area.

Note: If you select too big area, you won’t be able too select top zoom levels in the next steps.

bboxtool

4. Copy code in the grey box to your clipboard.

greybox

 

5. Open Taho application and paste the code into “Get from <bbox…>” field. Click on the bbox button now. It should populate coordinates into Taho application. Select UI-View in Kal.-Files, .jpg for file type, zoom level (16 is good for small city), size (should be free, whole area in 1 file), define path for saving your maps and click on make maps button.

steps

 

6. Each selected zoom level generates separate .jpg and .inf files in your defined maps path (step above).

7. Xastir doesn’t know how to handle .inf files so we need to convert them to .geo format. Upload your .jpg and .inf files to Xastir map folder. In my case, maps are located in  /usr/share/xastir/maps Fire up your linux console and

Download inf2geo.pl converter and convert .inf files:

sudo cd /usr/share/xastir/scripts
sudo wget https://raw.githubusercontent.com/mgrennan/xastir/master/scripts/inf2geo.pl
sudo chmod +x inf2geo.pl
sudo ./inf2geo.pl /usr/share/xastir/maps/yourmap.inf

By now, you should have yourmap.geo file in /usr/share/xastir/maps
Open .geo file with your favourite editor and correct the path if you have to.

FILENAME    maps/yourmap.jpg
TIEPOINT    0           0       16.0645 45.8288333333333
TIEPOINT    5631        5887    14.661666666667        46.8525
IMAGESIZE   5632        5888
#5632x5888
#
# Converted from a .INF file by WE7U's inf2geo.pl script
#

Note: If you change the name of the file, you also have to change FILENAME in yourmap.geo accordingly.

8. Start or restart Xastir, go to Map -> Map Chooser -> select your map -> Apply -> profit.