#!/bin/bash
#
# This script is used to update the firmware of the Moitessier HAT microcontroller.
# The latest firmware will be loaded automatically form an online repository.
# 
# Ensure that you have the I2C module and the flashing tool compiled (see 
# https://github.com/mr-rooney/moitessier for further information). You might
# need to change the paths below.
#
# Usage: ./fw_update_moitessier -h
#
# Most common commands:
#   sudo moitessier/scripts/production_test -k -s --ignore 2>&1 | tee ~/Desktop/production_test.log
#   sudo moitessier/scripts/production_test -k -x --ignore 2>&1 | tee ~/Desktop/production_test.log
#   sudo moitessier/scripts/production_test -k -s 2>&1 | tee ~/Desktop/production_test.log
#   sudo moitessier/scripts/production_test -k -s -g 0 2>&1 | tee ~/Desktop/production_test.log

flasher=../flasher/fw_update_moitessier

eepromFlasher=../device_tree/eeprom_update_moitessier           # the path to the EEPROM update script (relative path)
sensorScript=../app/sensors/check_functionality                 # the path to the script used to check the sensor functionality (relative path)
sensorFile=../app/sensors/sensValues.txt                        # The file where the sensor readouts should be stored
overlayPath=/boot/overlays                                      # the path to the device tree overlay directory on the Raspberry Pi (absolute path)
configFile=/boot/config.txt                                     # the boot configuration file used by the Raspberry Pi (absolute path)
moitessierDeviceTree=../device_tree/moitessier.dtbo             # the compiled device tree, this will be used as overlay (relative path)
i2cDeviceNr=3                                                   # The bit banged I2C interface. This parameter must equal with the settings in the 
                                                                # device tree overlay. SDA and SCL for this interface are specified in the overlay.
                                                                # FIXME: currently the kernel 4.19 only supports I2C bus number 3.
device=/dev/moitessier.spi                                      # the device file to read the Moitessier HAT data                                                           
powerPinNumber=21                                               # The GPIO pin used to power cycle the board. This pin is only used for the production test adapter.
sensorIterations=1
database=/home/pi/Desktop/moitessier_db.txt
moitessierCtrl=../app/moitessier_ctrl/moitessier_ctrl
deviceCtrl=/dev/moitessier.ctrl
gnssLog=gnss.log                                                # the file where the GNSS data is logged used while fix testing

# Default values for sensor sanity check.
temperature=35                                                  # temperature in C       
temperatureRange=15                                             # actual range is temperature +/- temperatureRange
pressure=1000                                                   # pressure in mbar
pressureRange=200                                               # actual range is pressure +/- pressureRange


dtparamI2CValid=0
dtoverlayMoitessierValid=0
dtoverlayI2CgpioValid=0

bus=/dev/i2c-${i2cDeviceNr}    

pwd="`dirname \"$0\"`"

# https://misc.flogisoft.com/bash/tip_colors_and_formatting
FORMAT_RED="\e[1;31m"
FORMAT_YELLOW="\e[1;93m"
FORMAT_GREEN="\e[1;32m"
FORMAT_DEFAULT="\e[0m"

unload()
{
    echo "INFO: Unloading \"$1\"."
	rmmod $1
}

help()
{
    echo
    echo "******************************************************************************************"
    echo "This script is used to test the Moitessier HAT."
    echo       
    echo "Available options:"
    echo "    -k                : If set the device tree overlay will be kept."
    echo "    -s                : If set the board will shutdown afterwards."
    echo "    -r                : If set the board will reboot afterwards."
    echo "    -x                : If set the board will not shutdown/reboot afterwards."
    echo "    -g N              : If set the board finish the test only if a GNSS fix is accomplished or a timeout occurs."
    echo "                          N...0  --> no timeout"
    echo "                          N...>0 --> timeout in seconds"
    echo "    -e N              : If set the board will test external GNSS antenna."
    echo "                          N...0  --> no timeout"
    echo "                          N...>0 --> timeout in seconds"
    echo "    -w                : If set the test will be finished by pressing a button of the keyboard."
    echo "    -b                : If set the shutdown button will be tested."
    echo "    -t                : Button test timeout."
    echo "    -a T,TR,P,PR      : The values for the sanity check of the sensors."
    echo "                          T  --> temperature"
    echo "                          TR --> temperature range"
    echo "                          P  --> pressure"
    echo "                          PR --> pressure range"
    echo "    --ignore          : If set errors will be ignored and tests will be continued. This option should"
    echo "                        be set if you want to test all functions of the board and you do not want to"
    echo "                        abort at the first found error."
    echo "******************************************************************************************"
    echo
}

error()
{
    echo
    echo "******************************************************************************************"
    echo -e "${FORMAT_RED}ERROR occured!!${FORMAT_DEFAULT}"
    echo
    echo -e "${FORMAT_RED}${1}${FORMAT_DEFAULT}"
    echo "******************************************************************************************"
    echo
}

warning()
{
    echo
    echo "******************************************************************************************"
    echo -e "${FORMAT_YELLOW}WARNING!!${FORMAT_DEFAULT}"
    echo
    echo -e "${FORMAT_YELLOW}${1}${FORMAT_DEFAULT}"
    echo "******************************************************************************************"
    echo
}

info()
{
    echo
    echo "******************************************************************************************"
    echo $1
    echo "******************************************************************************************"
    echo
}

results()
{
    echo
    echo "******************************************************************************************"
    echo -e "**************************************\e[1;45m TEST RESULTS ${FORMAT_DEFAULT}**************************************"
    echo "******************************************************************************************"
    echo
    format=${FORMAT_RED}        
    if [ "${systemFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${systemFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "SYSTEM                             ${format}${systemFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${sensorsFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${sensorsFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "SENSORS                            ${format}${sensorsFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${firmwareFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${firmwareFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "FIRMWARE                           ${format}${firmwareFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${eepromFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${eepromFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "EEPROM                             ${format}${eepromFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${gpioFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${gpioFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "GPIO                               ${format}${gpioFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${microcontrollerFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${microcontrollerFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "MICROCONTROLLER                    ${format}${microcontrollerFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${receiverFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${receiverFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "RECEIVER                           ${format}${receiverFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${gnssFixFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${gnssFixFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "GNSS FIX (INTERNAL ANTENNA)        ${format}${gnssFixFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${gnssExtAntFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${gnssExtAntFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "EXTERNAL GNSS ANTENNA DETECTED     ${format}${gnssExtAntFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${gnssFixExtAntFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${gnssFixExtAntFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "GNSS FIX (EXTERNAL ANTENNA)        ${format}${gnssFixExtAntFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${buttonFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${buttonFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "SHUTDOWN BUTTON                    ${format}${buttonFailed}${FORMAT_DEFAULT}"
    
    format=${FORMAT_RED}
    if [ "${databaseFailed}" == "${TEST_OK}" ]
    then        
        format=${FORMAT_GREEN}
    elif [ "${databaseFailed}" == "${NOT_TESTED}" ]
    then
        format=${FORMAT_YELLOW}
    fi
    echo -e "DATABASE                           ${format}${databaseFailed}${FORMAT_DEFAULT}"
    
    echo "******************************************************************************************"
    echo
}

# we are logging the production test in a board specific log file
logDir=/home/pi/Desktop/production                              # the directory where log files should be stored
# create log directory
if [ ! -d "${logDir}" ]; then
    mkdir ${logDir}
    if [ $? -ne 0 ]
    then
        error "Creating directory \"${logDir}\" failed"
        exit 1
    else
        info "Created directory \"${logDir}\""
    fi
fi
tmpLogFile=tmp.log
exec > >(tee -i ${logDir}/${tmpLogFile})
exec 2>&1

help

nOption="-n"
kOption=
sOption=0
rOption=0
xOption=0
ignoreOption=0
gOption=0
gCycles=0
wOption=0
bOption=0
tCycles=0
eOption=0
eCycles=0
aOption=0
aArg=""

NOT_TESTED="not tested"
TEST_OK="ok"
TEST_NOK="failed"

sensorsFailed=${NOT_TESTED}
firmwareFailed=${NOT_TESTED}
eepromFailed=${NOT_TESTED}
receiverFailed=${NOT_TESTED}
microcontrollerFailed=${NOT_TESTED}
databaseFailed=${NOT_TESTED}
gpioFailed=${NOT_TESTED}
systemFailed=${NOT_TESTED}
gnssFixFailed=${NOT_TESTED}
gnssExtAntFailed=${NOT_TESTED}
gnssFixExtAntFailed=${NOT_TESTED}
buttonFailed=${NOT_TESTED}

while getopts "kshxr-:g:wbt:e:a:" option
do
    case $option in
        k) kOption="-k"
            ;;
        s) sOption=1
            ;;
        r) rOption=1
            ;;
        h) exit 0
            ;;
        x) xOption=1
            ;;
        g) gOption=1
            gCycles=${OPTARG}
            ;;
        e) eOption=1
            eCycles=${OPTARG}
            ;;     
        a) aOption=1
            aArg=${OPTARG}
            ;;        
        w) wOption=1
            ;;                
        b) bOption=1
            ;;                
        t) tOption=1
            tCycles=${OPTARG}
            ;;        
        -) case "${OPTARG}" in
                ignore)
                    ignoreOption=1
                    ;;
                *) echo
                    error "Invalid option."
                    exit 1
                    ;;                    
            esac
            ;;            
        \?) echo
            error "Invalid option."
            exit 1
            ;;
    esac
done

# check if we have the proper rights
if [ "$EUID" -ne 0 ]
then 
    error "You must run this script with root privileges."
    exit
fi

if [ ${gOption} -eq 0 ] && [ ${eOption} -eq 0 ]
then
    warning "GNSS fix (external/internal antenna) is not tested"    
fi 

if [ ${gOption} -eq 0 ] && [ ${eOption} -eq 1 ]
then
    warning "GNSS fix (external antenna) is not tested"    
fi 

if [ ${aOption} -eq 1 ]
then
    IFS=',' # char , is set as delimiter
    read -ra sanityValues <<< "${aArg}" # string is read into an array as tokens separated by IFS
    temperature=${sanityValues[0]} 
    temperatureRange=${sanityValues[1]}            
    pressure=${sanityValues[2]}                  
    pressureRange=${sanityValues[3]}   
    IFS=' ' # reset to default value after usage
fi    
 
 
# only one boot option must be defined
bootOption=$(expr $rOption + $sOption + $xOption)
if [ $bootOption -gt 1 ]
then
    error "Option -r, -s and/or -n must not be applied at the same time."
    exit 1
fi

# check if the relevant parameters are set in the configuration file to load the device tree
while IFS='' read -r line || [[ -n "$line" ]]; do
    if [ "$line" = "dtparam=i2c_vc=on" ]
    then
        dtparamI2CValid=1
    fi
    if [ "$line" = "dtoverlay=moitessier" ]
    then
        dtoverlayMoitessierValid=1
    fi
    if [ "$line" = "dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,bus=${i2cDeviceNr}" ]
    then
        dtoverlayI2CgpioValid=1
    fi
done < "$configFile"

if [ $dtparamI2CValid == "0" ]
then    
    sh -c "echo 'dtparam=i2c_vc=on' >> $configFile"
fi
    
if [ $dtoverlayMoitessierValid == "0" ]
then    
    sh -c "echo 'dtoverlay=moitessier' >> $configFile"
fi

if [ $dtoverlayI2CgpioValid == "0" ]
then    
    sh -c "echo 'dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,bus=${i2cDeviceNr}' >> $configFile"
fi

cp "${pwd}/${moitessierDeviceTree}" ${overlayPath}
if [ $? -ne 0 ]
then
    error "Copying device tree \"${pwd}/${moitessierDeviceTree}\" to \"${overlayPath}\" failed."
    systemFailed=${TEST_NOK}
    results
    exit 1
else
    systemFailed=${TEST_OK}    
fi

# we need to reboot the Raspberry Pi to apply the changes in the configuration
if [ $dtparamI2CValid == "0" -o $dtoverlayMoitessierValid == "0" -o $dtoverlayI2CgpioValid == "0" ] 
then
    info "${configFile} has been changed. System will reboot. You need to call this script afterwards again."
    sleep 4
    reboot
fi

# check the sensors
"${pwd}/${sensorScript}" -i ${bus} -c ${sensorIterations} --mpu --press --cpu -s -t ${temperature} -r ${temperatureRange} -p ${pressure} -n ${pressureRange}
if [ $? -ne 0 ]
then
    error "Checking sensors failed. This might be okay, if one of the sensors is not assembled on the board."
    sensorsFailed=${TEST_NOK}
    if [ $ignoreOption == "1" ]
    then
        sleep 3  
    else
        results
        exit 1      
    fi
else
    sensorsFailed=${TEST_OK}
fi

# check if the file exists where the sensor data has been written and parse the values
if [ -e "${pwd}/${sensorFile}" ]
then
    sensValues=$(cat "${pwd}/${sensorFile}")
    while IFS=';' read -ra ADDR; do
        for i in "${ADDR[@]}"; do
            param=$(echo $i | sed 's/:.*//')
            val=$(echo $i | sed 's/.*://' | sed 's/;.*//')
            
            case "$param" in
                "cpuTemp") cpuTemp=$val;;
                "pressureTemp") pressureTemp=$val;;
                "pressure") pressure=$val;;
                "mpuTemp") mpuTemp=$val;;
                "*") error "Found value in ${pwd}/${sensorFile} that cannot be processed"
            esac
        done
    done <<< "$sensValues"
    rm "${pwd}/${sensorFile}"
    if [ $? -ne 0 ]
    then
        error "Could not delete file ${pwd}/${sensorFile}"
        sensorsFailed=${TEST_NOK}
        if [ $ignoreOption == "1" ]
        then
            sleep 3  
        else
            results
            exit 1      
        fi
    fi
else    
    error "File ${pwd}/${sensorFile} not found"
    sensorsFailed=${TEST_NOK}
    if [ $ignoreOption == "1" ]
    then
        sleep 3  
    else
        results
        exit 1      
    fi
fi

# write the firmware of the microcontroller
dir="`dirname \"${pwd}/${flasher}\"`"
"${pwd}/${flasher}" -s "${dir}/application.binary"
if [ $? -ne 0 ]
then
    error "Writing firmware failed"
    firmwareFailed=${TEST_NOK}
    results
    exit 1
else
    firmwareFailed=${TEST_OK}
fi

info "power cycling Moitessier HAT"
if [ -d "/sys/class/gpio/gpio${powerPinNumber}" ]
then
    echo ${powerPinNumber} > /sys/class/gpio/unexport
fi    
echo ${powerPinNumber} > /sys/class/gpio/export
if [ $? -ne 0 ]
then
    error "Exporting pin gpio${powerPinNumber} failed"
    gpioFailed=${TEST_NOK}
    results
    exit 1
else
    gpioFailed=${TEST_OK}
fi
echo "out" > /sys/class/gpio/gpio${powerPinNumber}/direction
echo 0 > /sys/class/gpio/gpio${powerPinNumber}/value
sleep 0.2
echo 1 > /sys/class/gpio/gpio${powerPinNumber}/value
sleep 1
echo 0 > /sys/class/gpio/gpio${powerPinNumber}/value
sleep 2

# write the EEPROM
"${pwd}/${eepromFlasher}" ${nOption} ${kOption}
if [ $? -ne 0 ]
then
    error "Writing EEPROM failed"
    eepromFailed=${TEST_NOK}
    results
    if [ $ignoreOption == "1" ]
    then
        sleep 3  
    else
        results
        exit 1      
    fi
else
    eepromFailed=${TEST_OK}
fi

# check the microcontroller and read relevant information
# get the serial number
serial=$("${pwd}/${moitessierCtrl}" ${deviceCtrl} 1 | grep serial)
if [ $? -ne 0 ]
then
    error "Could not get serial number from device"
    microcontrollerFailed=${TEST_NOK}
    results
    exit 1
else
    microcontrollerFailed=${TEST_OK}
    #serial=${serial#"serial - "}
fi

# get the ranging values for the AIS receiver
rng=$("${pwd}/${moitessierCtrl}" ${deviceCtrl} 1 | grep rng)
if [ $? -ne 0 ]
then
    error "Could not get rng from device"
    microcontrollerFailed=${TEST_NOK}
    results
    exit 1
else
    microcontrollerFailed=${TEST_OK}
fi

# get the firmware/app version
appVersion=$("${pwd}/${moitessierCtrl}" ${deviceCtrl} 1 | grep "app version")
if [ $? -ne 0 ]
then
    error "Could not get app version"
    microcontrollerFailed=${TEST_NOK}
    results
    exit 1
else
    microcontrollerFailed=${TEST_OK}
fi

# get the hardware revision
hwVersion=$("${pwd}/${moitessierCtrl}" ${deviceCtrl} 1 | grep "hardware version")
if [ $? -ne 0 ]
then
    error "Could not get hardware version"
    microcontrollerFailed=${TEST_NOK}
    results
    exit 1
else
    microcontrollerFailed=${TEST_OK}
fi

# get the GNSS firmware version
gnssVersion=$("${pwd}/${moitessierCtrl}" ${deviceCtrl} 1 | grep "gnss version")
if [ $? -ne 0 ]
then
    error "Could not get gnss version"
    microcontrollerFailed=${TEST_NOK}
    results
    exit 1
else
    microcontrollerFailed=${TEST_OK}
fi

# check AIS and GNSS
IFS=$'\r\n' GLOBIGNORE='*' command eval  'dat=($(head -n 60 ${device}))'
printf '%s\n' "${dat[@]}"

ais1Valid=0
ais1Cnt=0
ais2Valid=0
ais2Cnt=0
gnssValid=0
gnssCnt=0
for i in "${dat[@]}"
do
	echo $i
	if [[ "$i" == *"!AIVDM,1,1,,A,"* ]]
	then
	    ais1Valid=1
	    ((ais1Cnt++))
	fi
	
	if [[ "$i" == *"!AIVDM,1,1,,B,"* ]]
	then
	    ais2Valid=1
	    ((ais2Cnt++))
	fi
	
	if [[ "$i" == *"GPRMC"* ]]
	then
	    gnssValid=1
	    ((gnssCnt++))
	fi
	
	if [[ "$i" == *"GNRMC"* ]]
	then
	    gnssValid=1
	    ((gnssCnt++))
	fi
done

# evaluate the results of AIS and GNSS
if [ $gnssValid -eq 1 ] && [ $ais1Valid -eq 1 ] && [ $ais2Valid -eq 1 ]
then
    info "AIS/GNSS successfull - AIS1 = ${ais1Cnt}, AIS2 = ${ais2Cnt}, GNSS = ${gnssCnt}"
    receiverFailed=${TEST_OK}
else
    error "AIS/GNSS failed"
    receiverFailed=${TEST_NOK}
    if [ $ignoreOption == "1" ]
    then
        sleep 3  
    else
        results
        exit 1      
    fi
fi


# checking GNSS fix with internal antenna
fixFound=0
k=0

if [ ${gOption} -eq 1 ]
then
    info "Checking GNSS fix (internal patch antenna)"
    
    cat ${device} > ${gnssLog} &
    echo
    while true
    do
        dat=$(cat ${gnssLog} | grep ".*G[P|N]RMC,[^,]*,A,*")
        if [ $? -eq 0 ]
        then
            fixFound=1
            echo
            echo $dat
            break
        fi
        sleep 1
        echo -n "*"
        if [ $gCycles -ne 0 ]
        then
            k=$((k+1))
            if [ $k -ge $gCycles ]
            then
                echo
                break
            fi
        fi
    done
    
    kill %1 
    
    rm ${gnssLog} 
fi

gFix=-1 # GNSS fix not tested (internal antenna)
if [ $gOption -eq 1 ]
then
    if [ $fixFound -eq 1 ]
    then
        gFix=1
        gnssFixFailed=${TEST_OK}
        info "GNSS fix (internal antenna)"
    else
        gFix=0
        gnssFixFailed=${TEST_NOK}
        error "no GNSS fix (internal antenna)"
        if [ $ignoreOption == "1" ]
        then
            sleep 3  
        else
            results
            exit 1      
        fi
    fi
fi  




# checking external GNSS antenna
extAntOk=0
k=0

if [ ${eOption} -eq 1 ]
then
    info "Checking external GNSS antenna"
    
    info "Attach external GNSS antenna and press [ENTER] to continue"
    while [ true ]
    do    
        read -s -N 1 key
        if [[ $key == $'\x0a' ]];        # if input == ENTER key
        then
            break
        else
            echo "Only the ENTER key will be accepted"
        fi
    done
    
    # start reading data in a background process and store it in a log file
    cat ${device} > ${gnssLog} &
    echo
    while true
    do
        # do we received the proper NMEA sentence?
        # the GNSS module will send $GPTXT,01,01,02,ANTSTATUS=OK*3B if an external antenna is connected,
        # otherwise $GPTXT,01,01,02,ANTSTATUS=OPEN*2B
        dat=$(cat ${gnssLog} | grep ".*ANTSTATUS=OK*")
        if [ $? -eq 0 ]     # external antenna is detected
        then
            extAntOk=1
            echo
            echo $dat
            break
        fi
        sleep 1
        echo -n "*"
        
        # is a timeout defined?
        if [ $eCycles -ne 0 ]
        then
            k=$((k+1))
            if [ $k -ge $eCycles ]  # timeout occured
            then
                echo
                break
            fi
        fi
    done
    
    kill %1 
    
    rm ${gnssLog} 
fi

extAnt=-1 # external GNSS antenna not tested
if [ $eOption -eq 1 ]
then
    if [ $extAntOk -eq 1 ]  # external antenna detected
    then
        extAnt=1
        gnssExtAntFailed=${TEST_OK}
        info "external GNSS antenna detected"
    else    # extenal antenna not detected, timeout occured
        extAnt=0
        gnssExtAntFailed=${TEST_NOK}
        error "no external GNSS antenna detected"
        if [ $ignoreOption == "1" ]
        then
            sleep 3  
        else
            results
            exit 1      
        fi
    fi
fi   

# checking GNSS fix with external antenna
fixExtAntFound=0
k=0

if [ ${gOption} -eq 1 ] && [ $eOption -eq 1 ] && [ $extAnt -eq 1 ]
then
    info "Checking GNSS fix (external antenna)"
    
    cat ${device} > ${gnssLog} &
    echo
    while true
    do
        # do we received the proper NMEA sentence ($GNRMC or $GPRMC with valid flag set to 'A'?
        dat=$(cat ${gnssLog} | grep ".*G[P|N]RMC,[^,]*,A,*")
        if [ $? -eq 0 ]     # we have a fix, yeah
        then
            fixExtAntFound=1
            echo
            echo $dat
            break
        fi
        sleep 1
        echo -n "*"
        
        # is a timeout defined?
        if [ $gCycles -ne 0 ]
        then
            k=$((k+1))
            if [ $k -ge $gCycles ]  # timeout occured, we will abort
            then
                echo
                break
            fi
        fi
    done
    
    kill %1 
    
    rm ${gnssLog} 
fi

gExtAntFix=-1 # GNSS fix not tested (external antenna)
if [ ${gOption} -eq 1 ] && [ $eOption -eq 1 ]
then
    if [ $fixExtAntFound -eq 1 ]
    then
        gExtAntFix=1
        gnssFixExtAntFailed=${TEST_OK}
        info "GNSS fix (external antenna)"
    else
        gExtAntFix=0
        gnssFixExtAntFailed=${TEST_NOK}
        error "no GNSS fix (external antenna)"
        if [ $ignoreOption == "1" ]
        then
            sleep 3  
        else
            results
            exit 1      
        fi
    fi
fi   

# check shutdown button
buttonResult=-1 # button not tested
k=0
if [ ${bOption} -eq 1 ]
then
    buttonFailed=${TEST_NOK}
    
    # enable button test mode
    echo 1 | sudo tee /sys/module/moitessier/parameters/TEST_MODE_SHUTDOWN_BUTTON
    
    info "Press shutdown button"
    info "To abort the test enter the q character"
    
    toSearch="moitessier_thread - Shutting down"
    
    log1=$(dmesg | grep "${toSearch}")
    
    while true
    do
        log2=$(dmesg | grep "${toSearch}")
        
        #check if strings are not equal
        if [ "${log1}" != "${log2}" ]
        then
            #check if string holds the proper substring
            if [[ $log2 == *"${toSearch}"* ]]
            then
                buttonResult=1
                buttonFailed=${TEST_OK}
                info "button tested successfully"
                break;
            fi
        fi
        echo -n "*"
        read -t 1 -s -N 1 key
        if [[ $key == 'q' ]];        # if input == q key
        then
            buttonResult=0
            buttonFailed=${TEST_NOK}
            error "button failed - tested aborted"
            if [ $ignoreOption == "1" ]
            then
                sleep 3 
                break 
            else
                results
                exit 1      
            fi
        fi
        
        if [ $tCycles -ne 0 ]
        then
            k=$((k+1))
            if [ $k -ge $tCycles ]
            then
                buttonResult=0
                buttonFailed=${TEST_NOK}
                error "button failed - timeout"
                if [ $ignoreOption == "1" ]
                then
                    sleep 3  
                    break
                else
                    results
                    exit 1      
                fi
            fi
        fi
    done
    
    # disable button test mode
    echo 0 | sudo tee /sys/module/moitessier/parameters/TEST_MODE_SHUTDOWN_BUTTON
fi


# get the timestamp via Internet
timestamp=$(wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f5-8)
if [ $? -ne 0 ]
then
    error "Could not get current internet time"
    results
    exit 1
fi

# any errors?
if [ "$sensorsFailed" != "${TEST_OK}" -o "$firmwareFailed" != "${TEST_OK}" -o "$eepromFailed" != "${TEST_OK}" -o "$receiverFailed" != "${TEST_OK}" -o "$microcontrollerFailed" != "${TEST_OK}" -o "$gpioFailed" != "${TEST_OK}" -o "$systemFailed" != "${TEST_OK}" -o "$buttonFailed" == "${TEST_NOK}" -o "$gnssFixFailed" == "${TEST_NOK}" -o "$gnssExtAntFailed" == "${TEST_NOK}" -o "$gnssFixExtAntFailed" == "${TEST_NOK}" ]
then
    results
    exit 1
fi

if [ ! -e "${database}" ]
then
    info "creating database"
    touch "${database}"
    if [ $? -ne 0 ]
    then
        error "Could not create database file ${database}"
        databaseFailed=${TEST_NOK}
        results
        exit 1
    else
        databaseFailed=${TEST_OK}
    fi
    
    chmod 666 ${database}
    if [ $? -ne 0 ]
    then
        error "Could not change access mode of database file ${database}"
        databaseFailed=${TEST_NOK}
        results
        exit 1
    else
        databaseFailed=${TEST_OK}
    fi
fi

kernelVersion=$(uname -r)
if [ $? -ne 0 ]
then
    warning "Could not get kernel version"
    kernelVersion="unkown"
fi
debianVersion=$(cat /etc/debian_version)
if [ $? -ne 0 ]
then
    warning "Could not get Debian version"
    debianVersion="unkown"
fi
piVersion=$(cat /proc/cpuinfo | grep "Model")
if [ $? -ne 0 ]
then
    warning "Could not get Raspberry Pi version"
    piVersion="unkown"
fi
moitessierVersion=$(dpkg -s moitessier | grep "Version:")
if [ $? -ne 0 ]
then
    warning "Could not get Moitessier package version"
    piVersion="unkown"
fi

# create database entry
dbEntry=${kernelVersion}";"${debianVersion}";"${piVersion}";"${moitessierVersion}";"${timestamp}";"${serial}";"${rng}";"${appVersion}";"${hwVersion}";"${ais1Cnt}";"${ais2Cnt}";"${gnssCnt}";"${cpuTemp}";"${pressureTemp}";"${pressure}";"${mpuTemp}";"${gFix}";"${extAnt}";"${gExtAntFix}";"${gnssVersion}";"${buttonResult}
# replace tabs with spaces
dbEntryFormatted2=$(echo ${dbEntry//$'\t'/ })

# delete CR und LF
dbEntryFormatted1=$(echo ${dbEntryFormatted2//$'\r'/})
dbEntryFormatted=$(echo ${dbEntryFormatted1//$'\n'/})



if [ ${#dbEntryFormatted} -eq 0 ]
then
    error "Could not write database file ${database} - string error"
    databaseFailed=${TEST_NOK}
    results
    exit 1
fi    

echo "Database entry: "${dbEntryFormatted}

# write to database    
echo ${dbEntryFormatted} >> ${database}
if [ $? -ne 0 ]
then
    error "Could not write database file ${database}"
    databaseFailed=${TEST_NOK}
    results
    exit 1
else
    databaseFailed=${TEST_OK}
fi

# verify if writing was successfull
verification=$(cat ${database} | grep "${dbEntryFormatted}")
if [ "${verification}" != "${dbEntryFormatted}" ]
then
    error "Database verification failed"
    databaseFailed=${TEST_NOK}
    results
    exit 1
else
    databaseFailed=${TEST_OK}
fi

results

# rename the temporary log file so we could archiv any production test cycle
if [ -e "${logDir}/${tmpLogFile}" ]
then
    fileName=${logDir}"/production_test_"${serial}"_"${timestamp}
    mv "${logDir}/${tmpLogFile}" "${fileName}"
    if [ $? -ne 0 ]
    then
        error "Could not rename file \"${logDir}/${tmpLogFile}\""
        exit 1
    fi
    
    chmod 666 "${fileName}"
    if [ $? -ne 0 ]
    then
        error "Could not change access mode of log file \"${fileName}\""
        exit 1
    fi
else
    error "\"${logDir}/${tmpLogFile}\" does not exist"
    exit 1
fi    

if [ ${wOption} -eq 1 ]
then
    info "Press [ENTER] to continue"
    while [ true ]
    do    
        read -s -N 1 key
        if [[ $key == $'\x0a' ]];        # if input == ENTER key
        then
            break
        else
            echo "Only the ENTER key will be accepted"
        fi
    done
else
    sleep 2    
fi    

if [ ${sOption} -eq 1 ]
then
    info "shutting down system"
    sleep 1
    shutdown now
fi    

if [ ${rOption} -eq 1 ]
then
    info "rebooting system"
    sleep 1
    reboot
fi   
exit 0
