Contents
In this article I will expose how I built a VHF (1200bps AX25 APRS) to UHF LoRa APRS Bridge without going through APRS-IS (Internet). This is work in progress, feel free to comment and come back to make sure you are up to date with the latest version of this project.
Introduction
I always considered APRS to be a full two-way system. Lately there has been a trend to turn it into a dumb one-way internet dependent vehicle tracking system, especially in the LoRa APRS world. The poor WB4APR must be spinning in his grave at high RPM. APRS is about being aware of your “ham-radio” surrounding.
Ok, enough of ranting. Since LoRa APRS is booming in Germany just across the border, I decided to give it a try. I thought it is quite sad that 1200bps AX25APRS and LoRa APRS just coexist without any bridges in between. As a matter of fact I started thinking about how to build a bridge between the two worlds so as both sides are locally aware of each other.
My first thought was to use APRS-IS, but this turned out to be a pain in the *ss, as it is almost impossible to cherry pick only the LoRa stations. Finally I came out with an onsite solution which does not require the internet at all! Perfect for remote sites without internet!
Requirements
Here are the requirements I had in mind:
- Only pass directly heard packets. This has the beauty to restrict the range of the bridge to the actual RF covered area of both technologies. No fancy geographical filters are needed. It also prevents looping between the two worlds.
Digipeating any packet that has already been digipeated can cause loops between VHF and LoRA and is detrimental to both networks as it will cloak both channels: DO NOT DO IT!
ONLY CROSSBAND DIRECTLY HEARD PACKETS ! - Only pass positions and messages. Digipating objects,telemetry,items,weather is considered spam on VHF thus I consider them to be spam when digipeated on LoRa.
- Rate Limit packets based on callsign. This is to mitigate people who think it is ok to beacon with a 6sec beacon rate.
- Single responsibility principle: Be able to stop the bridge and keep the VHF and LoRa running separately
Prerequisites
From now on, I assume you already have the following things working. For the sake of conciseness, I will not describe how to set these things up, Google and the documentation of the involved software are your friends.
VHF APRS AX25 1200bps
You need to have one of the following:
- A running AX25 setup using the Linux AX25 Stack
– OR – - A KISS TNC connected through serial port
– OR – - A KISS TNC exposed through TCP
I went for the latter option, as I already had it up and running. The AX25 stack setup was working but, somehow, APRX was not happy about using different callsigns than the ones specified on the underlying AX25 interfaces.
UHF LoRa
What you need:
- A LoRa device running a recent version of the iGate/digipeater firmware by CA2RXU.
- Activate following options:
- Enable TNC server
- Enable Serial KISS
Bridging
The bridge will be done using APRX. APRX is a digipeater software capable of handling multiple ports. It can be configured to only allow digipeating between certain ports.
I assume you have it compiled and installed and that you also know how to start it.
Principle
My setup consists of the following:
- Direwolf handling the VHF part. It does all the digipeating on its own.
- LoRa handling is done by a simple TTGO, it is autonomous and does all the digipeating on its own.
We have these two blocks and now we need to configure aprx to act as a bridge between the two world.
Here is a simple diagram of the whole system:
Configuring APRX
While I was never impressed by APRX’s igating capabilities I always regarded it as a very good an highly configurable digipeater software.
To meet our requirement of only digipeating directly heard poisitions and messages we need to setup APRX the proper way. We do not want APRX to digipeat anything on the same band, this is handled by Direwolf and the TTGO.
Below is a copy of my aprx.conf setup. I am using AX25 stack on both LoRa and VHF. I tried to explain each option as much as good as I can.
For some reason, APRX needs to operate under distinct callsigns on each bands. Otherwise, I observed some strange effects on its own beacons.
The VHF side will be opearting under F4FXL-4 and the LoRa side as F4FXL-11
# This is the callsign and SSID our bridge wil operate under,
# we do not need it as each band will have it's own callsign
# yet we need to specify it otherwise APRX won't TX beacons (bug ?)
mycall F4FXL-11
# !!!!! this the location of the bridge used in beacons, adjust to your own!
myloc lat 4849.50N lon 00736.28E
# Below is some logging stuff
<logging>
pidfile /var/run/aprx.pid
rflog /var/log/aprx/aprx-rf.log
aprxlog /var/log/aprx/aprx.log
#erlangfile /var/run/aprx.state
</logging>
# here we define all the interfaces
# F4FXL-4 is the VHF interface
<interface>
tcp-device 127.0.0.1 8001 KISS # this is the direwolf IP
callsign F4FXL-4
tx-ok true # this interface is allowed to transmit
telem-to-is false # we do not want the traffic channel telemetry
</interface>
# F4FXL-11 is the LoRa interface
<interface>
tcp-device 192.168.123.192 8001 KISS # this is the TTGO on my LAN
callsign F4FXL-11 # this interface is allowed to transmit
tx-ok true
telem-to-is false
</interface>
# Below we define the beacons which are sent over the air
# First beacon block goes out on LoRa
<beacon>
beaconmode radio
cycle-size 30m
beacon symbol B# $myloc comment "VHF <=> LoRa Bridge (LoRa Side)" srccall F4FXL-11 interface F4FXL-11 via WIDE1-1
beacon symbol B# $myloc comment "VHF <=> LoRa bridge (LoRa Side)" srccall F4FXL-11 interface F4FXL-11
</beacon>
# Second beacon block goes out on VHF
<beacon>
beaconmode radio
cycle-size 30m
beacon symbol B# $myloc comment "VHF <=> LoRa Bridge (VHF Side)" srccall F4FXL-4 interface F4FXL-4 via WIDE1-1
beacon symbol B# $myloc comment "VHF <=> LoRa bridge (VHF Side)" srccall F4FXL-4 interface F4FXL-4
</beacon>
#Here we define the digipeaters with their sources and transmitters
#LoRa to VHF
<digipeater>
transmitter F4FXL-4 # VHF is our outgoing interface
srcratelimit 3 6 # channel flood protection allow max 3 (peak 6) packet/minutes/callsign
<source>
source F4FXL-11 # LoRa is our incoming interface
relay-type directonly # restrict to directly heard frames
regex-filter data ^\} # somehow the blocking of 3rd party frames does not always work, hence this
filter t/pmq # We only pass positions, messages and queries
filter -t/3cinostuw # block everything else
<trace>
keys WIDE # only apply WIDEn-N paradigm
</trace>
</source>
</digipeater>
#VHF to LoRa
<digipeater>
transmitter F4FXL-11 # LoRa is our outgoing interface
srcratelimit 3 6 # channel flood protection allow max 3 (peak 6) packets/minutes/callsign
<source>
source F4FXL-4 # VHF is our incoming interface
relay-type directonly # restrict to directly heard frames
regex-filter data ^\} # somehow the blocking of 3rd party frames does not always work, hence this
filter t/pmq # only allow positions, messages and queries
filter -t/3cinostuw # block everything else
<trace>
keys WIDE #only apply WIDEn-N paradigm
</trace>
</source>
</digipeater>
Code language: Apache (apache)
How it works
a packet entering VHF as
F1ABC>APRS,WIDE1-1,WIDE2-1:blabla
Code language: CSS (css)
will got out on LoRa as
F1ABC>APRS,F4FXL-11*,WIDE2-1:blabla
Code language: CSS (css)
The other way around, a packet entering LoRa as
F1ABC>APRS,WIDE1-1,WIDE2-1:blabla
Code language: CSS (css)
will go out on VHF as
F1ABC>APRS,F4FXL-4*,WIDE2-1:blabla
Code language: CSS (css)
Revision History
May 30th 2024: first publication
May 31st 2024: correct typo in diagram
June 1st 2024: clarify why it is important to only cross band directly heard packets!
June 3rd 2024: Tighten 3rd Party Filter
Pingback: Lora VHF crosband (bridge) – KutuKupret colorful website