#!/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-1 and saves these to file.
# Generate and send acknowledge message when incomming message ask for it.
# 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

# Direectory 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  d \*).+?\>"<<<$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  d \*).+?\>"<<<$LINE)"
            PORT="ax1"
       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  d \*).+?:'<<<$LINE)"
        else
            FULL_PATH="$(grep -o -P '(?<=PE1RXF-2  d \*).+?:'<<<$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)"
        
        # 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 channel ax1) send it via beacon
        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
            else

                # 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[@]}"

            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 65- | sed 's/{.*//'  | tr -d "[:blank:]")"

        #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

