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.
307 lines
14 KiB
307 lines
14 KiB
#!/bin/bash
|
|
|
|
##################################################################################
|
|
# Background process started by the initializing script start_aprs_server.sh #
|
|
# #
|
|
# It processes all incomming messages for PE1RXF and sends acknowledges when #
|
|
# if asked for (via kissutil for ax0 and beacon for ax1. It also prosesses the #
|
|
# special telemetry messages from PE1RXF devices. #
|
|
# #
|
|
# (C)2021 M.T. Konstapel https://meezenest.nl/mees #
|
|
# #
|
|
# This file is part of PE1RXF-APRS-server. #
|
|
# #
|
|
# PE1RXF-APRS-server is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# PE1RXF-APRS-server is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the GNU General Public License #
|
|
# along with PE1RXF-APRS-server If not, see <https://www.gnu.org/licenses/>. #
|
|
# #
|
|
##################################################################################
|
|
|
|
# Filters out all APRS messages to PE1RXF (all suffixes) and saves these to file.
|
|
# Generate and send acknowledge message when incomming message ask for it (only for -1, -2 and -3 suffixes).
|
|
# Also, reads APRS message and when it is telemetry converts it to a format readeble by gnuplot
|
|
#
|
|
# The script aprs_utils.sh starts a filters means of tail | grep on the log file of aprx.
|
|
# The output of this command goes to this script via stdin. This script reads this line by line
|
|
# and sends an acknowledgement to the stations asking for one. This is done via kissutil, which
|
|
# is also started the script aprs_utils.sh
|
|
|
|
# Directory where kissutils expect files to send
|
|
APRS_SEND_MESSAGE_DIRECTORY=/home/marcel/ham/aprs_utils/aprs_files_to_transmit/
|
|
|
|
# Directory where APRS messages are stored
|
|
APRS_RECEIVED_MESSAGES_DIR=/home/marcel/ham/aprs_utils/aprs_log/
|
|
MESSAGE_FILE=aprs_received_messages.log
|
|
|
|
# Get current date YYYY-MM-DD
|
|
#CURRENT_DATE=$(date +"%Y-%m-%d")
|
|
|
|
#Read file line by line and send acknowledge if needed
|
|
while read LINE
|
|
do
|
|
|
|
#################
|
|
# Section: filter out APRS messages and generate acknowledge if needed
|
|
#################
|
|
|
|
# Get current date YYYY-MM-DD (do this every time, because a day may already have passed)
|
|
CURRENT_DATE=$(date +"%Y-%m-%d")
|
|
CURRENT_DATE_TIME=$(date +"%Y-%m-%d %H:%M:%S")
|
|
|
|
# figure out who sent the message
|
|
# Check channel 1 (internal radio)
|
|
#CALL="$(grep -o -P "(?<=PE1RXF-1 R \*).+?\>"<<<$LINE)"
|
|
CALL="$(grep -oP "(?<=PE1RXF-1 R ).+?\>"<<<$LINE)"
|
|
PORT="ax0"
|
|
|
|
# If call is empty, frame not from channel 1, maybe from channel 2?
|
|
if [ -z $CALL ]; then
|
|
#CALL="$(grep -o -P "(?<=PE1RXF-2 R \*).+?\>"<<<$LINE)"
|
|
CALL="$(grep -oP "(?<=PE1RXF-2 R ).+?\>"<<<$LINE)"
|
|
PORT="ax1"
|
|
fi
|
|
|
|
# If call is empty, frame not from channel 1 or 2, maybe from channel 3?
|
|
if [ -z $CALL ]; then
|
|
#CALL="$(grep -o -P "(?<=PE1RXF-2 R \*).+?\>"<<<$LINE)"
|
|
CALL="$(grep -oP "(?<=PE1RXF-3 R ).+?\>"<<<$LINE)"
|
|
PORT="ax2"
|
|
fi
|
|
|
|
# If call is empty, frame not from channel 1, 2 or 3, maybe from channel APRSIS?
|
|
if [ -z $CALL ]; then
|
|
#CALL="$(grep -o -P "(?<=PE1RXF-2 R \*).+?\>"<<<$LINE)"
|
|
CALL="$(grep -oP "(?<=APRSIS R ).+?\>"<<<$LINE)"
|
|
PORT="aprsis"
|
|
fi
|
|
|
|
# Lets do something with the message from channel 1 or 2
|
|
if [[ $CALL ]]; then
|
|
|
|
# Remove last character from string
|
|
CALL=${CALL::-1}
|
|
|
|
ACKNOWLEDGE_NUMBER="$(grep -o -P '(?<={).*'<<<$LINE)"
|
|
|
|
#Write messages to file with name "YYYY-MM-DD_messages_from_NOCALL.log (append)
|
|
#echo "$LINE" >> "$APRS_RECEIVED_MESSAGES_DIR""$CURRENT_DATE""_messages_from_""$CALL"".log"
|
|
|
|
# Get full path of message
|
|
if [ $PORT == "ax0" ]; then
|
|
#FULL_PATH="$(grep -o -P '(?<=PE1RXF-1 R \*).+?:'<<<$LINE)"
|
|
FULL_PATH="$(grep -oP "(?<=PE1RXF-1 R ).+?:"<<<$LINE)"
|
|
elif [ $PORT == "ax1" ]; then
|
|
#FULL_PATH="$(grep -o -P '(?<=PE1RXF-2 R \*).+?:'<<<$LINE)"
|
|
FULL_PATH="$(grep -oP "(?<=PE1RXF-2 R ).+?:"<<<$LINE)"
|
|
elif [ $PORT == "ax2" ]; then
|
|
#FULL_PATH="$(grep -o -P '(?<=PE1RXF-2 R \*).+?:'<<<$LINE)"
|
|
FULL_PATH="$(grep -oP "(?<=PE1RXF-3 R ).+?:"<<<$LINE)"
|
|
elif [ $PORT == "aprsis" ]; then
|
|
#FULL_PATH="$(grep -o -P '(?<=PE1RXF-2 R \*).+?:'<<<$LINE)"
|
|
FULL_PATH="$(grep -oP "(?<=APRSIS R ).+?:"<<<$LINE)"
|
|
fi
|
|
|
|
FULL_PATH="$(grep -o -P '(?<=\>).*'<<<$FULL_PATH)"
|
|
# Remove last character from string
|
|
FULL_PATH=${FULL_PATH::-1}
|
|
|
|
# Messages direct from sender do not contain a '*' in the path
|
|
DIRECT="$(grep '*' <<<$FULL_PATH)"
|
|
if [ -z $DIRECT ]; then
|
|
DIRECT="true"
|
|
else
|
|
unset DIRECT
|
|
fi
|
|
# First call in path is destination
|
|
DESTINATION="$(awk -F "," '{ print $1} ' <<<$FULL_PATH)"
|
|
|
|
# get the message
|
|
MESSAGE="$(grep -o -P '(?<=::).*'<<<$LINE)"
|
|
MESSAGE="$(grep -o -P '(?<=:).*'<<<$MESSAGE)"
|
|
|
|
# get the receipient of the message
|
|
RECEIPIENT="$(grep -o -P '(?<=::).+?:'<<<$LINE)"
|
|
RECEIPIENT=${RECEIPIENT::-1}
|
|
|
|
# Write message to file
|
|
echo "$CURRENT_DATE_TIME"",""$PORT"",""$CALL"",""$DESTINATION",\"$MESSAGE\" >> "$APRS_RECEIVED_MESSAGES_DIR""$MESSAGE_FILE"
|
|
|
|
#Send incomming message as email
|
|
#echo "$LINE" | /home/marcel/ham/aprs_utils/send_aprs_message_to_email.sh
|
|
|
|
#Generate acknowledge frame and put in in de directory where kissutil can find (ax0) it or (for channels ax1 and ax2) send it via beacon
|
|
if [[ $RECEIPIENT == "PE1RXF-1 " || $RECEIPIENT == "PE1RXF-2 " || $RECEIPIENT == "PE1RXF-3 " ]]; then
|
|
if [[ $ACKNOWLEDGE_NUMBER ]]; then
|
|
|
|
# if call is less than 9 characters, add spaces at the end (according to the APRS protocol)
|
|
printf -v FORMATTED_CALL %-9.9s "$CALL"
|
|
|
|
OWN_CALL="$(grep "PE1RXF"<<<$CALL)"
|
|
|
|
# Message on port ax0
|
|
if [ $PORT == "ax0" ]; then
|
|
|
|
# Local (own) stations do not need to be digipeated
|
|
if [ $OWN_CALL ]; then
|
|
APRS_FRAME="PE1RXF-1>APRX29::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
# Everyone else is digipeated
|
|
else
|
|
APRS_FRAME="PE1RXF-1>APRX29,WIDE2-2::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
fi
|
|
|
|
# Send acknowledge frame
|
|
APRS_TRANSMIT_FILE="acknowledge_""$FORMATTED_CALL""_message_""$ACKNOWLEDGE_NUMBER"
|
|
echo "$APRS_FRAME" > "$APRS_SEND_MESSAGE_DIRECTORY$APRS_TRANSMIT_FILE"
|
|
|
|
# Message on port ax1
|
|
elif [ $PORT == "ax1" ]; then
|
|
|
|
# Local (own) stations do not need to be digipeated
|
|
if [ $OWN_CALL ]; then
|
|
APRS_HEADER="APRX29"
|
|
APRS_FRAME="::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
args[0]=-d
|
|
args[1]="APRX29"
|
|
args[2]=-s
|
|
args[3]=ax1
|
|
args[4]=":$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
# Everyone else is digipeated
|
|
else
|
|
APRS_HEADER="APRX29 WIDE2-2"
|
|
APRS_FRAME="::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
args[0]=-d
|
|
args[1]="APRX29 WIDE2-2"
|
|
args[2]=-s
|
|
args[3]=ax1
|
|
args[4]=":$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
fi
|
|
|
|
# use beacon to send acknowledge frame
|
|
#echo "/usr/sbin/beacon -d '$APRS_HEADER' -s ax1 '$APRS_FRAME'"
|
|
#/usr/sbin/beacon -d "$APRS_HEADER" -s ax1 "$APRS_FRAME"
|
|
/usr/sbin/beacon "${args[@]}"
|
|
|
|
# Message on port ax2
|
|
elif [ $PORT == "ax2" ]; then
|
|
|
|
# Local (own) stations do not need to be digipeated
|
|
if [ $OWN_CALL ]; then
|
|
APRS_HEADER="APRX29"
|
|
APRS_FRAME="::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
args[0]=-d
|
|
args[1]="APRX29"
|
|
args[2]=-s
|
|
args[3]=ax2
|
|
args[4]=":$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
# Everyone else is digipeated
|
|
else
|
|
APRS_HEADER="APRX29 WIDE2-2"
|
|
APRS_FRAME="::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
args[0]=-d
|
|
args[1]="APRX29 WIDE2-2"
|
|
args[2]=-s
|
|
args[3]=ax2
|
|
args[4]=":$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
fi
|
|
|
|
# use beacon to send acknowledge frame
|
|
#echo "/usr/sbin/beacon -d '$APRS_HEADER' -s ax1 '$APRS_FRAME'"
|
|
#/usr/sbin/beacon -d "$APRS_HEADER" -s ax1 "$APRS_FRAME"
|
|
/usr/sbin/beacon "${args[@]}"
|
|
|
|
# Message on port aprsis, send ack on LoRa as this channel has the most iGATEs
|
|
elif [ $PORT == "aprsis" ]; then
|
|
|
|
# Local (own) stations do not need to be digipeated
|
|
if [ $OWN_CALL ]; then
|
|
APRS_HEADER="APRX29"
|
|
APRS_FRAME="::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
args[0]=-d
|
|
args[1]="APRX29"
|
|
args[2]=-s
|
|
args[3]=ax2
|
|
args[4]=":$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
# Everyone else is digipeated
|
|
else
|
|
APRS_HEADER="APRX29 WIDE2-2"
|
|
APRS_FRAME="::$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
args[0]=-d
|
|
args[1]="APRX29 WIDE2-2"
|
|
args[2]=-s
|
|
args[3]=ax2
|
|
args[4]=":$FORMATTED_CALL:ack$ACKNOWLEDGE_NUMBER"
|
|
fi
|
|
|
|
# use beacon to send acknowledge frame
|
|
#echo "/usr/sbin/beacon -d '$APRS_HEADER' -s ax1 '$APRS_FRAME'"
|
|
#/usr/sbin/beacon -d "$APRS_HEADER" -s ax1 "$APRS_FRAME"
|
|
/usr/sbin/beacon "${args[@]}"
|
|
|
|
fi
|
|
|
|
fi
|
|
fi
|
|
|
|
#################
|
|
# Section: process APRS telemetry to format readable by gnuplot
|
|
#################
|
|
|
|
# get date field
|
|
DATE="$(echo $LINE | cut -b 1-10)"
|
|
|
|
# get time field
|
|
TIME="$(echo $LINE | cut -b 12-16)"
|
|
|
|
# get telemetry fields and remove empty spaces and optional acknowledge message if it is present
|
|
#TELEMETRY="$(echo $LINE | cut -b 64- | sed 's/{.*//' | tr -d "[:blank:]")"
|
|
TELEMETRY="$(echo $LINE | cut -b 63- | sed 's/{.*//' | tr -d "[:blank:]")"
|
|
|
|
echo $LINE
|
|
echo $TELEMETRY
|
|
|
|
#Datafiled should have comma as field seperator, so asume this and put values in array for later testing if data is valid
|
|
IFS=',' read -r -a array <<< "$TELEMETRY"
|
|
|
|
# Test if message contains valid numbers. It could be an acknowledge or beacon etc.
|
|
TELEMETRY_ERROR=0
|
|
for index in "${!array[@]}"
|
|
do
|
|
|
|
if ! [[ ${array[index]} =~ ^-?[0-9]+([.][0-9]+)?$ ]] ; then
|
|
TELEMETRY_ERROR=1
|
|
fi
|
|
|
|
done
|
|
|
|
# If telemetry message is valid, store it (change APRS date/time (UTM) with local time)
|
|
if [ $TELEMETRY_ERROR -eq 0 ] ; then
|
|
|
|
# Get current date and time YYYY-MM-DD %H:%M for local time stamp (do this every time, because a day may already have passed)
|
|
LOCAL_DATE_TIME=$(date +"%Y-%m-%d %H:%M")
|
|
|
|
#Format line by combining all needed fields
|
|
DATA_STRING="$(echo "$LOCAL_DATE_TIME","$TELEMETRY")"
|
|
#| tr -d "[:blank:]")"
|
|
|
|
#Write messages to file with name "YYYY-MM-DD_telemetry_NOCALL.log (append)
|
|
echo "$DATA_STRING" >> "$APRS_RECEIVED_MESSAGES_DIR""$CURRENT_DATE""_telemetry_""$CALL"".dat"
|
|
|
|
#Write last telemetry message to file (overwrite) for current values
|
|
echo "$TELEMETRY" > "$APRS_RECEIVED_MESSAGES_DIR""latest_telemetry_""$CALL"".dat"
|
|
|
|
fi
|
|
|
|
fi
|
|
# end channel 1
|
|
|
|
done < /dev/stdin
|
|
|
|
|