This project is a collection of former (and some new) projects connected together to make an APRS digipeater, which doubles as an APRS weather station, with PE1RXF telemetry server capabilities.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

482 lines
18 KiB

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<meta name="author" content="M.T. Konstapel" />
<meta name="dcterms.date" content="2024-02-14" />
<title>APRS digipeater installation guide</title>
<link rel="stylesheet" href="./css/mvp.css" />
<style type="text/css">
:root {
--width-content: 1080px;
}
nav {
justify-content: space-around;
}
</style>
</head>
<body>
<header id="title-block-header">
<nav id="TOC">
<ul>
<li>
<a href="#">Index</a>
<ul>
<li><a
href="#installation-guide-pe1rxf-aprs-digipeater-and-weather-station"
id="toc-installation-guide-pe1rxf-aprs-digipeater-and-weather-station">Installation
guide PE1RXF APRS digipeater and weather station</a></li>
<li><a href="#preparing-the-sd-card"
id="toc-preparing-the-sd-card">Preparing the SD
card</a></li>
<li><a href="#before-the-first-boot"
id="toc-before-the-first-boot">Before the first
boot</a></li>
<li><a href="#the-pi-is-booted-for-the-first-time"
id="toc-the-pi-is-booted-for-the-first-time">The Pi is
booted for the first time</a></li>
<li><a href="#from-a-vanilla-pi-to-an-aprs-digipeater"
id="toc-from-a-vanilla-pi-to-an-aprs-digipeater">From a
vanilla Pi to an APRS digipeater</a></li>
<li><a href="#backup-sd-card" id="toc-backup-sd-card">Backup
SD card!</a></li>
</ul>
</li>
<li>
<a href="https://git.meezenest.nl/marcel/aprs_digipeater">Git repo</a>
</li>
<li>
<a href="https://meezenest.nl/mees/aprs_digipeater.html">Back</a>
</li>
</ul>
<a href="https://www.meezenest.nl/mees/"><img alt="Logo" src="./images/mees_logo.svg" height="70"></a>
</nav>
<h1 class="title">APRS digipeater installation guide</h1>
<p class="subtitle">not for the faint of heart</p>
<p class="author">M.T. Konstapel</p>
<p class="date">2024-02-14</p>
</header>
<main>
<article>
<p><b>Abstract </b><p>This project is a collection of former (and some
new) projects connected together to make an APRS digipeater, which
doubles as an APRS weather station, with PE1RXF telemetry server
capabilities.</p></p>
<h1
id="installation-guide-pe1rxf-aprs-digipeater-and-weather-station">Installation
guide PE1RXF APRS digipeater and weather station</h1>
<p>This guide assumes you are using the LoRa hat for the Raspberry Pi
Zero from Mees Electronics.</p>
<h1 id="preparing-the-sd-card">Preparing the SD card</h1>
<p>Download the latest 32 bit version of Raspberry OS. Do not use the 64
bit version. It will probably work, but some software I use might not
work on 64 bit.</p>
<pre><code>$ unxz image_name.img.xz
$ sudo dd if=image_name.img of=/dev/name_of_block_device bs=4M conv=fsync status=progress</code></pre>
<h1 id="before-the-first-boot">Before the first boot</h1>
<h3 id="mount-the-boot-partition-on-a-computer.">Mount the boot
partition on a computer.</h3>
<h3 id="create-a-file-called-userconf-in-boot">Create a file called
“userconf” in /boot</h3>
<pre><code>$ nano userconf</code></pre>
<p>This file should only have one line of text, with
username:encrypted-password – that is, your preferred username, followed
by a colon, and then an encrypted representation of the password you
wish to use.</p>
<p>The simplest approach to generate the encrypted password is to use
OpenSSL on a Raspberry Pi that is already running — Activate a terminal
window and type: echo ‘frambozentaart’ | openssl passwd -6 -stdin This
will generate what appears to be a random string of characters, but is
really an encrypted version of the provided password.</p>
<p>This is the line that should go in userconf.txt:</p>
<pre><code>taart:$6$wOOBx/uscFupsHDn$PSjutVwKxZyGa9.11NP/wpy4Wtn4qA0Xx3AY5KvuzmxOm7En5l2/O33yNWISmWxTlWHzLuVaPnJO0ccYVdDNu0</code></pre>
<p>This defines user: ‘taart’ with password ‘frambozentaart’</p>
<h3 id="create-an-empty-file-called-ssh-in-boot">Create an empty file
called “ssh” in /boot</h3>
<pre><code>$ touch ssh</code></pre>
<h3 id="create-a-file-called-wpa_supplicant.conf-in-boot">Create a file
called “wpa_supplicant.conf” in /boot</h3>
<pre><code>$ nano wpa_supplicant.conf</code></pre>
<p>Add the following text:</p>
<pre><code>country=nl
update_config=1
ctrl_interface=/var/run/wpa_supplicant
network={
scan_ssid=1
ssid=&quot;Your WiFi Name&quot;
psk=&quot;Your WiFi Password&quot;
}</code></pre>
<h3 id="activate-auto-power-off-button">Activate Auto power off
button</h3>
<pre><code>$ nano config.txt</code></pre>
<p>Add the following text:</p>
<pre><code>dtoverlay=gpio-poweroff,gpiopin=21,active_low=&quot;y&quot;
dtoverlay=gpio-shutdown,gpio_pin=16</code></pre>
<p>GPIO21 goes high when RPi is booting and stays high until after
succesfully halting the processor with “sudo halt” or shutdown via
external button. When GPIO16 goes low (external button pressed), RPi
goes into shutdown.</p>
<h3
id="insert-the-sd-card-in-the-raspberry-pi-and-press-the-power-button">Insert
the SD card in the Raspberry Pi and press the power button</h3>
<p>During the first boot, the Pi will reboot once. Because of the
external power button, this will not work: the Pi will shutdown. Power
up the Pi by pressing the external power button again.</p>
<h1 id="the-pi-is-booted-for-the-first-time">The Pi is booted for the
first time</h1>
<p>Search for the ip address of the Raspberry Pi (for exammple by
logging into your router) and ssh into the Pi (user: taart, password:
frambozentaart)</p>
<h3 id="create-new-user">Create new user</h3>
<pre><code>$ sudo adduser user_name</code></pre>
<p>Add the new user to all the groups of the default user (taart)</p>
<pre><code>$ sudo nano /etc/group</code></pre>
<p>Replace taart by user_name ,taart (for example adm:x:4:taart becomes
adm_x:username,taart)</p>
<p>Add user to sudo group</p>
<pre><code>$ sudo usermod -aG sudo user_name</code></pre>
<p>Reboot the system and log in as new user.</p>
<p>Test user’s sudo permissions by executing a random command as sudo
(for example: sudo ls)</p>
<p>Remove default user taart</p>
<pre><code>$ sudo deluser -remove-home taart</code></pre>
<p>Disable auto-login.</p>
<pre><code>$ sudo raspi-config</code></pre>
<p>Set system-options / S5 Boot/Auto login / B1 Console</p>
<h3 id="login-with-ssh-without-password">Login with ssh without
password</h3>
<p>Create key on local machine</p>
<pre><code>$ ssh-keygen -t ed25519 -f ~/.ssh/aprs-weather-server -C &quot;marcel aprs-weather-server-server&quot;</code></pre>
<p>Copy the key to the Raspberry Pi</p>
<pre><code>$ ssh-copy-id -i ~/.ssh/aprs-weather-server.pub marcel@server_ip_address</code></pre>
<p>Log in on the Raspberry Pi without password</p>
<pre><code>$ ssh -o &quot;IdentitiesOnly=yes&quot; -i .ssh/aprs-weather-server &lt;IP-adres&gt;&gt;</code></pre>
<p>Optional: on the local machine edit .ssh/config and add the
server/key combination. Now you can log in with just “ssh
&lt;server-name”</p>
<h3 id="housekeeping">Housekeeping</h3>
<p>Change login screen via motd (message of the day).</p>
<pre><code>$ nano /etc/motd</code></pre>
<p>Change hostname.</p>
<pre><code>$ sudo nano /etc/hostname
$ sudo nano /etc/hosts</code></pre>
<p>Setting the locale</p>
<pre><code>$ sudo raspi-config</code></pre>
<p>Edit Localisation options / change locale (en_US.UTF-8 UTF-8) And set
time zone</p>
<p>For years now, Perl give Locale warnings. Fix it:</p>
<pre><code>$ sudo nano /etc/default/locale</code></pre>
<p>add:</p>
<pre><code>LC_ALL=en_US.UTF-8
LANGUAGE=en_US.UTF-8</code></pre>
<p>Update software</p>
<pre><code>$ sudo apt-get update
$ sudo apt-get upgrade</code></pre>
<h3 id="install-firewall">Install firewall</h3>
<pre><code>$ sudo apt install ufw
$ sudo ufw allow ssh
$ sudo ufw enable
$ sudo ufw status</code></pre>
<h1 id="from-a-vanilla-pi-to-an-aprs-digipeater">From a vanilla Pi to an
APRS digipeater</h1>
<h3 id="enable-i2c-rtc">Enable I2C RTC</h3>
<pre><code>$ sudo rapi-config</code></pre>
<p>enable i2c</p>
<pre><code>$ sudo reboot
$ sudo apt-get install i2c-tools
$ sudo i2cdetect -y 1</code></pre>
<p>#68 is RTC</p>
<pre><code>$ sudo nano /boot/firmware/config.txt</code></pre>
<p>Add dtoverlay=i2c-rtc,ds1307</p>
<pre><code>$ sudo reboot
$ sudo i2cdetect -y 1</code></pre>
<p>If UU appears instead of 68 then we have successfully loaded in the
Kernel driver for our RTC circuit.</p>
<p>Disable fake hardware clock:</p>
<pre><code>$ sudo apt-get -y remove fake-hwclock
$ sudo update-rc.d -f fake-hwclock remove
$ sudo systemctl disable fake-hwclock
$ sudo nano /lib/udev/hwclock-set</code></pre>
<p>Find</p>
<pre><code>if [ -e /run/systemd/system ] ; then
exit 0
fi</code></pre>
<p>Replace with:</p>
<pre><code>#if [ -e /run/systemd/system ] ; then
# exit 0
#fi</code></pre>
<p>Also comment out the two lines</p>
<pre><code>/sbin/hwclock --rtc=$dev --systz --badyear</code></pre>
<p>and</p>
<pre><code>/sbin/hwclock --rtc=$dev --systz</code></pre>
<p>Read RTC:</p>
<pre><code>$ sudo hwclock -r</code></pre>
<p>Set RTC from system time:</p>
<pre><code>$ sudo hwclock -w</code></pre>
<h3 id="ax.25-support">AX.25 support</h3>
<pre><code>$ sudo apt-get install libax25 ax25-apps ax25-tools
$ sudo nano /etc/ax25/axports</code></pre>
<p>add:</p>
<pre><code>ax0 PE1RXF-1 9600 255 2 144.800 MHz APRS (1200 bps)
ax1 PE1RXF-3 9600 255 2 433.775 MHz APRS (LORA)</code></pre>
<h3 id="aprx-software">APRX software</h3>
<pre><code>$ sudo apt-get install aprx
$ sudo systemctl enable aprx
$ sudo nano /etc/aprs.conf:</code></pre>
<p>Add the following (may be different on your machine)</p>
<pre><code>mycall PE1RXF-1
&lt;aprsis&gt;
passcode 19123
server euro.aprs2.net 14580
&lt;/aprsis&gt;
&lt;logging&gt;
pidfile /var/run/aprx.pid
rflog /var/log/aprx/aprx-rf.log
aprxlog /var/log/aprx/aprx.log
&lt;/logging&gt;
&lt;interface&gt;
ax25-device $mycall
tx-ok true # transmitter enable defaults to false
telem-to-is false # set to &#39;false&#39; to disable
&lt;/interface&gt;
#Secondary interface (internal LoRa radio)
&lt;interface&gt;
callsign PE1RXF-3
ax25-device PE1RXF-3
tx-ok true
telem-to-is false # set to &#39;false&#39; to disable
&lt;/interface&gt;
&lt;beacon&gt;
beaconmode aprsis
cycle-size 20m
beacon srccall PE1RXF-1 symbol &quot;R&amp;&quot; lat &quot;5302.78N&quot; lon &quot;00707.91E&quot; comment &quot;APRS RX iGATE 144.800MHz https://meezenest.nl/pe1rxf&quot;
&lt;/beacon&gt;
&lt;beacon&gt;
beaconmode aprsis
cycle-size 20m
beacon srccall PE1RXF-3 symbol &quot;L&amp;&quot; lat &quot;5302.78N&quot; lon &quot;00707.91E&quot; comment &quot;LoRa APRS RX iGATE 433.775MHz https://meezenest.nl/pe1rxf&quot;
&lt;/beacon&gt;
#&lt;beacon&gt;
# beaconmode radio
# cycle-size 30m
# beacon interface PE1RXF-3 symbol &quot;L&amp;&quot; lat &quot;5302.78N&quot; lon &quot;00707.91E&quot; comment &quot;LoRa APRS RX iGATE 433.775MHz https://meezenest.nl/pe1rxf&quot;
#&lt;/beacon&gt;
&lt;digipeater&gt;
transmitter $mycall
&lt;source&gt;
source $mycall
relay-type directonly
viscous-delay 5
# Forward enkel PE1RXF* (bij wet verboden om als relais voor derden te fungeren)
filter b/PE1RXF*
&lt;/source&gt;
&lt;source&gt;
source PE1RXF-3
relay-type directonly
viscous-delay 5
filter b/PE1RXF*
&lt;/source&gt;
&lt;/digipeater&gt;
# LoRa digipeater
&lt;digipeater&gt;
transmitter PE1RXF-3
&lt;source&gt;
source $mycall
relay-type directonly
viscous-delay 5
filter b/PE1RXF*
&lt;/source&gt;
&lt;source&gt;
source PE1RXF-3
relay-type directonly
viscous-delay 5
filter b/PE1RXF*
&lt;/source&gt;
&lt;/digipeater&gt;</code></pre>
<h3 id="some-commands-must-be-called-as-sudo">Some commands must be
called as sudo</h3>
<p>but we don’t want to enter the password all the time. Especcially at
boot time!</p>
<pre><code>$ sudo visudo</code></pre>
<p>Add:</p>
<pre><code>marcel ALL = (root) NOPASSWD: /usr/sbin/kissattach
marcel ALL = (root) NOPASSWD: /usr/sbin/kissparms
marcel ALL = (root) NOPASSWD: /usr/bin/socat
marcel ALL = (root) NOPASSWD: /usr/local/bin/tncattach</code></pre>
<h3 id="bd-packet-modem">1200bd packet modem</h3>
<pre><code>$ mkdir ham
$ cd ham
$ nano ~/ham/start_packetmodem_nano2.sh</code></pre>
<p>Add (make sure USB port is correct):</p>
<pre><code>#!/bin/bash
echo &quot;Starting packet modem nano 2&quot;
# Packet modem uses a CS340 chip, which does not have a serial number. If other USB devices
# with a CS340 chip are pluged in the software cannot distinquish between the various devices.
# But the modem is always connected to the same physical USB port. Use this port number
# instead of /dev/USBx.
serial_port=$(readlink -f /dev/serial/by-path/platform-3f980000.usb-usb-0:1.4:1.0-port0)
# Set serial port in RAW mode. Otherwise some charcters may be lost to the modem.
/usr/bin/stty -F $serial_port raw
sleep 1
sudo /usr/sbin/kissattach $serial_port ax0
sleep 1
sudo /usr/sbin/kissparms -p ax0 -t 500 -s 200 -r 32 -l 100 -f n</code></pre>
<p>Make file executable:</p>
<pre><code>$ chmod u+x ./start_packetmodem_nano2.sh</code></pre>
<h3 id="lora-aprs-modem">LoRa APRS modem</h3>
<pre><code>$ sudo apt-get install git
$ sudo raspi-config</code></pre>
<p>Enable SPI</p>
<pre><code>$ sudo apt-get install socat</code></pre>
<p>clone LoRa driver:</p>
<pre><code>$ cd ham
$ git clone https://git.meezenest.nl/marcel/RPi-LoRa-KISS-TNC.git</code></pre>
<p>In start_all.sh the line with socat probably says ax2, change to
ax1</p>
<h3 id="weather-station">Weather station</h3>
<pre><code>$ get the weather_station software, which is still under development (will be published on https://git.meezenest.nl/)
$ sudo apt install python3-pip</code></pre>
<p>Install pythonax25, which can be found at
~/ham/weather_station/python-ax25:</p>
<pre><code>$ cd ~/ham/weather_station/python-ax25
$ sudo ./install.sh</code></pre>
<p>Install other libraries:</p>
<pre><code>$ pip3 install minimalmodbus --break-system-packages
$ pip3 install retrying --break-system-packages
$ pip3 install pyaml --break-system-packages</code></pre>
<p>Add /home/marcel/.local/bin to path:</p>
<pre><code>$ nano .bashrc
add:
export PATH=/home/marcel/.local/bin:$PATH</code></pre>
<h3 id="rnode">Rnode</h3>
<pre><code>$ pip3 install rns --break-system-packages</code></pre>
<p>If the Rnode modem firmware is not yet installed on the ESP32 board
do:</p>
<pre><code>$ rnodeconf /dev/ttyACM0 --autoinstall</code></pre>
<p>Install tncattach:</p>
<pre><code>$ cd ~/ham
$ git clone https://github.com/markqvist/tncattach.git
$ cd tncattach
$ make
$ sudo make install
$ mkdir ~/ham/rnode_hamnet
$ nano ~/ham/rnode_hamnet/start_rnode.sh and add:</code></pre>
<p>Add:</p>
<pre><code>#!/bin/bash
# Set the Rnode in TNC mode on 434.25 MHz BW 500kHz Spreading Factor 7 Code Rate 4:5 Power 17dBm
# Ideally, this command should only be executed once.
/home/marcel/.local/bin/rnodeconf /dev/ttyACM0 -T --freq 434250000 --bw 500000 --txp 17 --sf 7 --cr 5
# Send station identification every 10 minutes
# mtu: 496 (PtP), 482 (ethernet) or 478 (ethernet with VLAN)
sudo /usr/local/bin/tncattach /dev/ttyACM0 115200 -d -e --mtu 482 --noipv6 --ipv4 192.168.44.2/24 --id PE1RXF -t 600</code></pre>
<p>Make executable:</p>
<pre><code>$ chmod u+x ./start_rnode.sh</code></pre>
<h3 id="routing">Routing</h3>
<p>To use this adapter for internet access change the default
gateway:</p>
<pre><code>$ sudo route add default gw 192.168.44.1 metric 30</code></pre>
<p>This gives the new route priority, because the already defined
default route has a metric of 100</p>
<p>Change metrics by removing the route and adding it again. The
exammple makes the old gateway the one with the higest priority:</p>
<pre><code>$ sudo route del default gw 192.168.44.1 metric 30
$ sudo route add default gw 192.168.44.1 metric 200</code></pre>
<p>chech with:</p>
<pre><code>$ ip route</code></pre>
<h3
id="and-also-on-the-server-site-enable-forwarding-and-nat-not-on-the-aprs-digipeater">And
also, on the server site, enable forwarding and nat (NOT ON THE APRS
DIGIPEATER!!!)</h3>
<pre><code>$ sudo echo &quot;1&quot; &gt; /proc/sys/net/ipv4/ip_forward
$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$ sudo iptables -A FORWARD -i eth0 -o tnc0 -m state --state RELATED,ESTABLISHED -j ACCEPT
$ sudo iptables -A FORWARD -i tnc0 -o eth0 -j ACCEPT</code></pre>
<p>NOTE: make these changes permanant….</p>
<pre><code>$ sudo nano /etc/sysctl.conf</code></pre>
<p>uncomment: net.ipv4.ip_forward=1</p>
<p>Maybe needed:</p>
<pre><code># Add the following statement somewhere at the beginning
# of /etc/dhcpcd.conf to prevent dhcpcd from changing MTU
denyinterfaces tnc0</code></pre>
<h3 id="start-script">Start script</h3>
<pre><code>$ nano ~/ham/start_aprs_server.sh</code></pre>
<p>Add:</p>
<pre><code>#!/bin/bash
echo &quot;Starting AX.25 interfaces&quot;
# initializing 1200bd packet modem
/home/marcel/ham/start_packetmodem_nano2.sh
# initializing LoRa modem
/home/marcel/ham/RPi-LoRa-KISS-TNC/start_all.sh
# initializing RNode network over LoRa
echo &quot;Starting LoRa network interface&quot;
/home/marcel/ham/rnode_hamnet/start_rnode.sh
# Start weather station software
echo &quot;Starting weather station&quot;
/home/marcel/ham/weather_station/start_weater_station.sh</code></pre>
<p>And make executable</p>
<pre><code>$ chmod u+x ./start_aprs_server.sh</code></pre>
<p>Add to crontab:</p>
<pre><code>$ crontab -e</code></pre>
<p>Add:</p>
<pre><code># Start APRS server at boot time (for some reason a 60 second wait is necessary)
@reboot sleep 60 &amp;&amp; /home/marcel/ham/start_aprs_server.sh</code></pre>
<p>TODO:</p>
<p>network route over RNode if ethernet is down</p>
<p>Webinterface for sending and receiving messages over APRS (forward to
e-mail?)</p>
<h1 id="backup-sd-card">Backup SD card!</h1>
<p>I use the script pishrink.sh to make an image.</p>
<hr>
</article>
</main>
<footer>
<p>&copy;
2024-02-14
M.T. Konstapel
<a href="https://meezenest.nl/mees/">https://meezenest.nl/mees/</a>
</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
</p>
</footer>
</body>
</html>